From 561d88aabb66fddbf321278845d4b359b3dc853a Mon Sep 17 00:00:00 2001 From: Saman Waqar Date: Thu, 19 Feb 2026 10:28:13 +0500 Subject: [PATCH] code-push-uco UCO Project --- .dart_tool/package_config.json | 1156 +++ .dart_tool/package_graph.json | 1724 +++++ .dart_tool/version | 1 + .flutter-plugins-dependencies | 1 + .idea/.gitignore | 19 + .idea/caches/deviceStreaming.xml | 1414 ++++ .idea/libraries/Dart_Packages.xml | 1532 ++++ .idea/libraries/Dart_SDK.xml | 31 + .idea/libraries/Flutter_Plugins.xml | 39 + .idea/misc.xml | 3 +- .idea/uco-mobile-poc.iml | 9 +- .idea/workspace.xml | 30 +- assets/.en | 0 assets/uco/icons/arrow.svg | 94 + assets/uco/icons/aud_flag.png | Bin 0 -> 9757 bytes assets/uco/icons/bankDetails.svg | 293 + assets/uco/icons/changePassoword.svg | 238 + assets/uco/icons/drop_down_ic.png | Bin 0 -> 814 bytes assets/uco/icons/euro_flag.png | Bin 0 -> 8996 bytes assets/uco/icons/gbp_flag.png | Bin 0 -> 3003 bytes assets/uco/icons/ic_QR.png | Bin 0 -> 6750 bytes assets/uco/icons/ic_QR.svg | 340 + assets/uco/icons/ic_activation.svg | 317 + assets/uco/icons/ic_activity.svg | 164 + assets/uco/icons/ic_add.svg | 92 + assets/uco/icons/ic_add_new_Account.png | Bin 0 -> 374 bytes assets/uco/icons/ic_arrow_down.svg | 102 + assets/uco/icons/ic_arrow_down_icon.png | Bin 0 -> 792 bytes assets/uco/icons/ic_back_arrow_appbar.svg | 253 + assets/uco/icons/ic_back_white.svg | 78 + assets/uco/icons/ic_bank_transfer.svg | 218 + assets/uco/icons/ic_bill.svg | 160 + assets/uco/icons/ic_call.svg | 234 + assets/uco/icons/ic_camera.svg | 451 ++ assets/uco/icons/ic_camera_profile.svg | 242 + assets/uco/icons/ic_chat.svg | 225 + assets/uco/icons/ic_check_status.svg | 181 + assets/uco/icons/ic_cheque_deposit.svg | 185 + assets/uco/icons/ic_cheque_management.svg | 117 + assets/uco/icons/ic_chnage_pin.svg | 269 + assets/uco/icons/ic_client.png | Bin 0 -> 4324 bytes assets/uco/icons/ic_client.svg | 303 + assets/uco/icons/ic_clock_circle.svg | 151 + assets/uco/icons/ic_congratulation.svg | 456 ++ assets/uco/icons/ic_congratulations!.svg | 343 + assets/uco/icons/ic_contact_us.png | Bin 0 -> 5688 bytes assets/uco/icons/ic_contact_us.svg | 429 ++ assets/uco/icons/ic_credit.svg | 117 + assets/uco/icons/ic_credit_card_bills.svg | 144 + assets/uco/icons/ic_cross.svg | 165 + assets/uco/icons/ic_cross_option.svg | 140 + assets/uco/icons/ic_cross_white.svg | 113 + assets/uco/icons/ic_current_account_arrow.svg | 160 + assets/uco/icons/ic_customer_service.svg | 159 + assets/uco/icons/ic_cyber_security.svg | 437 ++ assets/uco/icons/ic_daily_transaction.svg | 324 + assets/uco/icons/ic_debit.svg | 110 + assets/uco/icons/ic_debit_card.svg | 176 + .../uco/icons/ic_desposit_account_arrow.svg | 144 + assets/uco/icons/ic_device_management.svg | 319 + assets/uco/icons/ic_dollar_symbol.svg | 120 + assets/uco/icons/ic_download.svg | 136 + assets/uco/icons/ic_electricity.png | Bin 0 -> 2477 bytes assets/uco/icons/ic_email.svg | 246 + assets/uco/icons/ic_filter_statement.svg | 76 + assets/uco/icons/ic_finger_print.svg | 361 + assets/uco/icons/ic_fingerprint.svg | 645 ++ assets/uco/icons/ic_gas.png | Bin 0 -> 1928 bytes assets/uco/icons/ic_general_ledger.svg | 246 + assets/uco/icons/ic_government.png | Bin 0 -> 5091 bytes assets/uco/icons/ic_holding_money.svg | 360 + assets/uco/icons/ic_home_icon.svg | 143 + assets/uco/icons/ic_internet.png | Bin 0 -> 2083 bytes assets/uco/icons/ic_internet.svg | 471 ++ assets/uco/icons/ic_isb.png | Bin 0 -> 7133 bytes assets/uco/icons/ic_karachi.png | Bin 0 -> 4738 bytes assets/uco/icons/ic_kc.png | Bin 0 -> 6058 bytes assets/uco/icons/ic_ke.png | Bin 0 -> 3218 bytes assets/uco/icons/ic_khan.png | Bin 0 -> 6103 bytes assets/uco/icons/ic_kprogresshud_spinner.png | Bin 0 -> 3136 bytes assets/uco/icons/ic_kyc_unverified.svg | 116 + assets/uco/icons/ic_language.svg | 289 + assets/uco/icons/ic_link.png | Bin 0 -> 593 bytes assets/uco/icons/ic_location.svg | 217 + assets/uco/icons/ic_log_out.svg | 275 + assets/uco/icons/ic_logout.svg | 130 + assets/uco/icons/ic_manage_account.svg | 346 + assets/uco/icons/ic_menu_bar.svg | 73 + assets/uco/icons/ic_money_management.svg | 262 + assets/uco/icons/ic_multan.png | Bin 0 -> 6485 bytes assets/uco/icons/ic_next.svg | 84 + assets/uco/icons/ic_notifactions.svg | 142 + assets/uco/icons/ic_notification_filter.svg | 83 + assets/uco/icons/ic_pakistan.png | Bin 0 -> 22980 bytes assets/uco/icons/ic_person_setting.svg | 194 + assets/uco/icons/ic_phone.svg | 491 ++ assets/uco/icons/ic_phone_bottom_sheet.svg | 474 ++ assets/uco/icons/ic_qr_setting.svg | 277 + assets/uco/icons/ic_receiving_money.svg | 481 ++ assets/uco/icons/ic_request.svg | 315 + assets/uco/icons/ic_search.svg | 104 + assets/uco/icons/ic_security.png | Bin 0 -> 6995 bytes assets/uco/icons/ic_select_contact.svg | 46 + assets/uco/icons/ic_setting.svg | 291 + assets/uco/icons/ic_share.svg | 261 + assets/uco/icons/ic_share_qr.svg | 129 + assets/uco/icons/ic_snding_money.svg | 363 + assets/uco/icons/ic_sort.png | Bin 0 -> 436 bytes assets/uco/icons/ic_stop.svg | 118 + assets/uco/icons/ic_sub_accounts.svg | 239 + assets/uco/icons/ic_tick.svg | 96 + assets/uco/icons/ic_tick_option.svg | 150 + assets/uco/icons/ic_u_cash.svg | 186 + assets/uco/icons/ic_u_receive_menu.svg | 221 + assets/uco/icons/ic_u_recive.svg | 181 + assets/uco/icons/ic_u_shop.svg | 174 + assets/uco/icons/ic_user.svg | 216 + assets/uco/icons/ic_utility_bills.svg | 269 + assets/uco/icons/ic_voice.svg | 116 + assets/uco/icons/ic_wallet.svg | 217 + assets/uco/icons/ic_warning.png | Bin 0 -> 3227 bytes assets/uco/icons/ic_water.png | Bin 0 -> 2144 bytes assets/uco/icons/ic_wise_card.svg | 254 + assets/uco/icons/ind_flag.png | Bin 0 -> 6678 bytes assets/uco/icons/inviteFriendsUco.svg | 321 + assets/uco/icons/sending_icon.svg | 435 ++ assets/uco/icons/usa.png | Bin 0 -> 24439 bytes assets/uco/icons/use_flag.png | Bin 0 -> 7268 bytes assets/uco/images/im_qr.png | Bin 0 -> 26515 bytes assets/uco/images/img_country_flag.png | Bin 0 -> 882 bytes assets/uco/images/img_country_flag.svg | 9 + assets/uco/images/img_debet.png | Bin 0 -> 1271 bytes assets/uco/images/img_global.svg | 6789 +++++++++++++++++ assets/uco/images/img_intro_slider_1.png | Bin 0 -> 131598 bytes assets/uco/images/img_intro_slider_2.png | Bin 0 -> 64543 bytes .../uco/images/img_round_dashboard_card.png | Bin 0 -> 471 bytes assets/uco/images/img_slider.svg | 4901 ++++++++++++ assets/uco/logo/ic_dashboard_logo.svg | 942 +++ assets/uco/logo/ic_launcher.png | Bin 0 -> 154588 bytes assets/uco/logo/lg_back_arrow.svg | 151 + assets/uco/logo/lg_dialog_logo.svg | 1184 +++ assets/uco/logo/lg_lunch_icon.svg | 2720 +++++++ assets/uco/logo/lg_mfsys.png | Bin 0 -> 13300 bytes assets/uco/logo/lg_uco_logo_white.svg | 480 ++ assets/uco/logo/shopping-cart.png | Bin 0 -> 13735 bytes assets/uco/logo/uc-logo.png | Bin 0 -> 154588 bytes assets/uco/logo/uc_logo.png | Bin 0 -> 66657 bytes fonts/Inter-Black.ttf | 0 fonts/Inter-Bold.ttf | 0 fonts/Inter-ExtraBold.ttf | 0 fonts/Inter-ExtraLight.ttf | 0 fonts/Inter-Light.ttf | 0 fonts/Inter-Medium.ttf | 0 fonts/Inter-Regular.ttf | 0 fonts/Inter-SemiBold.ttf | 0 fonts/Inter-Thin.ttf | 0 fonts/Poppins-Medium.ttf | 0 fonts/Poppins-Regular.ttf | 0 lib/app/bindings/dependency_injections.dart | 26 + lib/app/core/config/api_utils.dart | 60 + lib/app/core/config/connectivity_service.dart | 46 + lib/app/core/config/dio_exceptions.dart | 93 + lib/app/core/config/error_message_model.dart | 41 + lib/app/core/config/logging.dart | 52 + lib/app/core/config/requset_attr.dart | 40 + lib/app/core/config/server_request.dart | 121 + lib/app/core/config/server_response.dart | 72 + lib/app/core/constants/PinType.dart | 4 + lib/app/core/constants/api_keys.dart | 141 + lib/app/core/constants/app_assets.dart | 141 + lib/app/core/constants/app_contants.dart | 88 + .../core/constants/form_field_constants.dart | 30 + lib/app/core/constants/translation_keys.dart | 344 + lib/app/core/constants/url_constants.dart | 100 + lib/app/core/constants/widget_types.dart | 4 + .../app_remote_data_source.dart | 706 ++ .../data/repositories/app_repositories.dart | 271 + lib/app/core/dialogs/custom_loading.dart | 162 + lib/app/core/enums/api_keys.dart | 66 + lib/app/core/enums/countryCode.dart | 7 + lib/app/core/enums/http_methods.dart | 1 + lib/app/core/enums/languageCode.dart | 7 + lib/app/core/enums/request_constants.dart | 8 + lib/app/core/enums/screen_type.dart | 1 + .../core/extensions/build_context_ext.dart | 61 + lib/app/core/local_stoarge/app_storage.dart | 169 + lib/app/core/utils/FingerPrintController.dart | 71 + lib/app/core/utils/SessionCache.dart | 79 + lib/app/core/utils/app_utils.dart | 93 + lib/app/core/utils/fields_utils.dart | 12 + lib/app/core/utils/globle_keys.dart | 1 + lib/app/core/utils/logs_utils.dart | 23 + lib/app/core/utils/phone_number_utils.dart | 9 + lib/app/core/utils/root_detector_device.dart | 45 + lib/app/core/utils/simulator_check.dart | 17 + lib/app/core/utils/url_encryption.dart | 59 + .../Fields/custom_dropdown_bottom_sheet.dart | 267 + .../Fields/field_validations.dart | 26 + .../custom_widgets/Fields/input_field.dart | 535 ++ lib/app/custom_widgets/bottom_sheet.dart | 212 + lib/app/custom_widgets/custom_app_bar.dart | 126 + lib/app/custom_widgets/custom_button.dart | 60 + .../custom_date_time_picker.dart | 298 + lib/app/custom_widgets/custom_dialog.dart | 605 ++ lib/app/custom_widgets/custom_dropdown.dart | 178 + .../custom_widgets/custom_input_field.dart | 330 + lib/app/custom_widgets/custom_label.dart | 49 + lib/app/custom_widgets/custom_no_record.dart | 34 + lib/app/custom_widgets/custom_text.dart | 65 + lib/app/custom_widgets/custom_toasty.dart | 16 + lib/app/custom_widgets/date_picker.dart | 94 + lib/app/custom_widgets/pop_dialog.dart | 108 + lib/app/custom_widgets/responsive_widget.dart | 29 + .../custom_widgets/widget_interactions.dart | 43 + lib/app/custom_widgets/widget_operation.dart | 7 + lib/app/l10n/Arabic.dart | 12 + lib/app/l10n/English.dart | 382 + .../models/AccountInquiryResponseModel.dart | 44 + lib/app/models/AddNewAccountRequestModel.dart | 34 + lib/app/models/AuthenticationRequest.dart | 47 + lib/app/models/AuthenticationResponse.dart | 52 + lib/app/models/BeneficiaryAccountModel.dart | 61 + lib/app/models/Branch.dart | 15 + lib/app/models/ChangePasswordRequest.dart | 32 + .../models/ChangeTransactionPinRequest.dart | 64 + .../CreateTransactionPinOTPRequest.dart | 57 + .../models/CreateTransactionPinRequest.dart | 49 + lib/app/models/DepositAccountResponse.dart | 152 + lib/app/models/DepositAccountTransaction.dart | 61 + lib/app/models/ExchangeRate.dart | 67 + lib/app/models/GLACCAddMoneyRequestModel.dart | 122 + .../models/GenerateReportRequestModel.dart | 40 + lib/app/models/GlsResponseModel.dart | 40 + lib/app/models/LoginResponseModel.dart | 87 + lib/app/models/RefreshToken.dart | 28 + lib/app/models/RegisterRequest.dart | 69 + .../SendTransactionStep1ResponseModel.dart | 24 + lib/app/models/SignupOtpRequest.dart | 62 + lib/app/models/SignupStep3RequestModel.dart | 97 + .../models/SubmitTransactionRequestModel.dart | 50 + .../SubmitTransactionResponseModel.dart | 28 + lib/app/models/TransactionHistoryRequest.dart | 40 + .../models/TransactionPinRequestModel.dart | 61 + .../models/TransactionPinResponseModel.dart | 28 + lib/app/models/TransactionRequestModel.dart | 56 + lib/app/models/TransactionResponseModel.dart | 22 + .../models/TransactionSubmitRequestModel.dart | 147 + .../TransactionSubmitResponseModel.dart | 26 + lib/app/models/UserActivity.dart | 48 + lib/app/models/UserActivityResponseModel.dart | 19 + lib/app/models/UserInfo.dart | 51 + lib/app/models/VerifyLoginOtpRequest.dart | 40 + lib/app/models/VerifySignupOtpRequest.dart | 52 + lib/app/models/ViewBalanceRequestModel.dart | 25 + lib/app/models/ViewBalanceResponseModel.dart | 22 + .../models/accept_receive_transaction.dart | 46 + .../models/accountStatementResponseModel.dart | 125 + lib/app/models/account_statment_model.dart | 43 + lib/app/models/chanange_password_params.dart | 36 + .../models/create_transition_otp_model.dart | 51 + lib/app/models/dashboard_response_model.dart | 59 + lib/app/models/evaluated_cuency_model.dart | 62 + lib/app/models/finger_print_info.dart | 36 + lib/app/models/identity_drop_down_model.dart | 12 + lib/app/models/login_request_model.dart | 35 + lib/app/models/product_model.dart | 43 + .../models/resen_ot_chanange_trans_pin.dart | 72 + lib/app/models/resend_ot_login_model.dart | 72 + lib/app/models/resend_otp_usend.dart | 66 + lib/app/models/reverse_transaction_model.dart | 28 + lib/app/models/u_recived_responce_model.dart | 125 + lib/app/models/upload_user_profile_model.dart | 28 + .../about_us/bindings/about_us_binding.dart | 12 + .../controllers/about_us_controller.dart | 23 + .../modules/about_us/views/about_us_view.dart | 45 + .../bindings/account_statement_binding.dart | 12 + .../account_statement_controller.dart | 319 + .../views/account_statement_view.dart | 145 + .../shared/account_Statement_widget.dart | 134 + .../add_money/bindings/add_money_binding.dart | 12 + .../bindings/add_money_otp_binding.dart | 12 + .../bindings/payment_method_binding.dart | 12 + .../controllers/add_money_controller.dart | 283 + .../controllers/add_money_otp_controller.dart | 91 + .../payment_method_controller.dart | 53 + .../add_money/views/add_money_view.dart | 278 + .../views/shared/account_list_screen.dart | 118 + .../views/shared/currency_list_screen.dart | 132 + .../add_money/views/shared/otp_add_money.dart | 155 + .../views/shared/payment_method_view.dart | 191 + .../bindings/add_new_binding.dart | 12 + .../add_new_account_controller.dart | 117 + .../views/add_new_account_view.dart | 92 + .../bindings/agent_location_binding.dart | 12 + .../agent_location_controller.dart | 142 + .../views/agent_location_view.dart | 95 + .../bindings/intro_screen_binding.dart | 12 + .../controllers/intro_screen_controller.dart | 23 + .../app_intro/views/intro_screen_view.dart | 123 + .../bindings/app_setting_binding.dart | 12 + .../controllers/app_setting_controller.dart | 62 + .../app_setting/views/app_setting_view.dart | 466 ++ .../app_setting/views/model/Language.dart | 16 + .../beneficiary_management_binding.dart | 13 + .../beneficiary_management_controller.dart | 76 + .../views/beneficiary_management_view.dart | 179 + .../beneficiary_transfer_binding.dart | 12 + .../beneficiary_transfer_controller.dart | 199 + .../views/beneficiary_transfer_view.dart | 394 + .../beneficiary_transfer_otp_binding.dart | 12 + .../beneficiary_transfer_otp_controller.dart | 75 + .../views/beneficiary_transfer_otp_view.dart | 138 + .../bindings/bill_management_binding.dart | 12 + .../bill_management_controller.dart | 6 + .../views/bill_management_view.dart | 149 + .../bill_management_category_binding.dart | 12 + .../bill_management_category_controller.dart | 247 + .../views/bill_management_category_view.dart | 116 + .../career/bindings/career_binding.dart | 12 + .../career/controllers/career_controller.dart | 23 + lib/app/modules/career/views/career_view.dart | 110 + .../change_transaction_pin_binding.dart | 12 + .../change_transaction_pin_controller.dart | 78 + .../views/change_transaction_pin_view.dart | 241 + .../change_transaction_pin_otp_binding.dart | 12 + ...change_transaction_pin_otp_controller.dart | 93 + .../change_transaction_pin_otp_view.dart | 134 + .../bindings/cheque_activation_binding.dart | 12 + .../cheque_activation_controller.dart | 23 + .../views/cheque_activation_view.dart | 138 + .../cheque_book_request_details_binding.dart | 12 + ...heque_book_request_details_controller.dart | 23 + .../cheque_book_request_details_view.dart | 334 + .../bindings/cheque_deposit_binding.dart | 12 + .../cheque_deposit_controller.dart | 12 + .../views/cheque_deposit_view.dart | 307 + .../bindings/cheque_management_binding.dart | 12 + .../cheque_management_controller.dart | 23 + .../views/cheque_management_view.dart | 103 + .../bindings/cheque_request_binding.dart | 12 + .../cheque_request_controller.dart | 23 + .../views/cheque_request_view.dart | 125 + .../bindings/cheque_status_binding.dart | 12 + .../controllers/cheque_status_controller.dart | 23 + .../views/cheque_status_view.dart | 95 + .../cheque_status_history_binding.dart | 12 + .../cheque_status_history_controller.dart | 23 + .../views/cheque_status_history_view.dart | 183 + .../bindings/contacts_screen_binding.dart | 12 + .../contacts_screen_controller.dart | 105 + .../views/contacts_screen_view.dart | 107 + .../create_transaction_pin_binding.dart | 12 + .../create_transaction_pin_controller.dart | 66 + .../views/create_transaction_pin_view.dart | 158 + .../create_transaction_pin_otp_binding.dart | 12 + ...create_transaction_pin_otp_controller.dart | 92 + .../create_transaction_pin_otp_view.dart | 136 + .../dail_transaction_limit_binding.dart | 12 + .../dail_transaction_limit_controller.dart | 9 + .../views/dail_transaction_limit_view.dart | 128 + .../bindings/dashboard_screen_binding.dart | 12 + .../dashboard_screen_controller.dart | 129 + .../views/dashboard_screen_view.dart | 78 + .../views/shared/bottom_sheet_icon.dart | 46 + .../dashboard/views/shared/drawer_data.dart | 344 + .../dashboard/views/shared/home_page.dart | 139 + .../views/shared/main_dash_board.dart | 905 +++ .../modules/faqs/bindings/faqs_binding.dart | 12 + .../bindings/faqs_first_screen_binding.dart | 12 + .../bindings/faqs_second_screen_binding.dart | 12 + .../bindings/faqs_third_screen_binding.dart | 12 + .../faqs/controllers/faqs_controller.dart | 1218 +++ .../faqs_first_screen_controller.dart | 27 + .../faqs_second_screen_controller.dart | 34 + .../faqs_third_screen_controller.dart | 12 + .../faqs/views/faqs_first_screen_view.dart | 111 + .../faqs/views/faqs_second_screen_view.dart | 104 + .../faqs/views/faqs_third_screen_view.dart | 63 + lib/app/modules/faqs/views/faqs_view.dart | 121 + lib/app/modules/faqs/views/model/FAQS.dart | 187 + .../bindings/general_ledger_binding.dart | 12 + .../general_ledger_controller.dart | 222 + .../views/general_ledger_view.dart | 178 + .../internal_transaction_binding.dart | 12 + .../internal_transaction_controller.dart | 186 + .../views/internal_transaction_view.dart | 402 + .../internal_transaction_otp_binding.dart | 13 + .../internal_transaction_otp_controller.dart | 78 + .../views/internal_transaction_otp_view.dart | 137 + .../login/bindings/login_screen_binding.dart | 12 + .../controllers/login_screen_controller.dart | 135 + .../login/views/login_screen_view.dart | 613 ++ .../views/shared/bottom_sheet_login.dart | 173 + .../views/shared/expaanded_container.dart | 28 + .../login/views/shared/login_widget.dart | 116 + .../login/views/shared/top_dialog.dart | 56 + .../bindings/o_t_p_screen_binding.dart | 12 + .../controllers/o_t_p_screen_controller.dart | 132 + .../login_otp/views/o_t_p_screen_view.dart | 186 + .../bindings/my_account_binding.dart | 12 + .../controllers/my_account_controller.dart | 84 + .../my_account/views/my_account_view.dart | 301 + .../bindings/new_beneficiary_binding.dart | 12 + .../new_beneficiary_controller.dart | 270 + .../views/new_beneficiary_view.dart | 238 + .../bindings/new_beneficiary_otp_binding.dart | 13 + .../new_beneficiary_otp_controller.dart | 94 + .../views/new_beneficiary_otp_view.dart | 139 + .../bindings/notifications_binding.dart | 12 + .../controllers/notifications_controller.dart | 109 + .../views/notifications_view.dart | 315 + .../bindings/password_change_binding.dart | 11 + .../password_change_controller.dart | 79 + .../views/password_change_view.dart | 102 + .../bindings/privacy_policy_binding.dart | 12 + .../privacy_policy_controller.dart | 23 + .../views/privacy_policy_view.dart | 143 + .../bindings/qr_setting_binding.dart | 12 + .../controllers/qr_setting_controller.dart | 130 + .../qr_setting/views/qr_scan_screen.dart | 322 + .../qr_setting/views/qr_setting_view.dart | 116 + .../qr_setting/views/qr_view_screen.dart | 50 + .../qr_setting/views/scanner_buttons.dart | 169 + .../bindings/recipient_details_binding.dart | 12 + .../recipient_details_controller.dart | 64 + .../views/recipient_details_view.dart | 265 + .../bindings/sample_fields_binding.dart | 12 + .../controllers/sample_fields_controller.dart | 35 + .../views/sample_fields_view.dart | 120 + .../bindings/sign_up_screen_otp_binding.dart | 12 + .../sign_up_screen_step1_binding.dart | 12 + .../sign_up_screen_step2_binding.dart | 12 + .../sign_up_screen_step3_binding.dart | 12 + .../sign_up_screen_otp_controller.dart | 120 + .../sign_up_screen_step1_controller.dart | 125 + .../sign_up_screen_step2_controller.dart | 241 + .../sign_up_screen_step3_controller.dart | 170 + .../sign_up/views/shared/camera_screen.dart | 95 + .../views/sign_up_screen_otp_view.dart | 135 + .../views/sign_up_screen_step1_view.dart | 136 + .../views/sign_up_screen_step2_view.dart | 253 + .../views/sign_up_screen_step3_view.dart | 264 + .../speed_dial/src/simple_speed_dial.dart | 372 + .../bindings/splash_screen_binding.dart | 12 + .../controllers/splash_screen_controller.dart | 23 + .../splash/views/splash_screen_view.dart | 49 + .../bindings/transaction_history_binding.dart | 12 + .../transaction_history_controller.dart | 23 + .../shared/hository_list_widget.dart | 149 + .../views/transaction_history_view.dart | 49 + .../bindings/u_received_binding.dart | 12 + .../controllers/u_received_controller.dart | 363 + .../u_received/views/u_received_view.dart | 153 + .../u_send/bindings/u_send_binding.dart | 12 + .../u_send/controllers/u_send_controller.dart | 394 + lib/app/modules/u_send/views/u_send_view.dart | 582 ++ .../bindings/u_send_otp_binding.dart | 12 + .../controllers/u_send_otp_controller.dart | 94 + .../u_send_otp/views/u_send_otp_view.dart | 137 + .../bindings/user_activity_binding.dart | 12 + .../controllers/user_activity_controller.dart | 78 + .../views/shared/date_time_dialog.dart | 89 + .../views/user_activity_view.dart | 192 + .../views/widgets/user_activity_widget.dart | 51 + .../bindings/user_profile_binding.dart | 12 + .../controllers/user_profile_controller.dart | 253 + .../views/account_details_view.dart | 121 + .../views/profile_details_view.dart | 145 + .../user_profile/views/user_profile_view.dart | 269 + .../utility_bills_payment_binding.dart | 12 + .../utility_bills_payment_controller.dart | 23 + .../views/utility_bills_payment_view.dart | 370 + ...ility_bills_selected_category_binding.dart | 12 + ...ty_bills_selected_category_controller.dart | 18 + .../utility_bills_selected_category_view.dart | 139 + ...lls_selected_category_details_binding.dart | 12 + ..._selected_category_details_controller.dart | 23 + ..._bills_selected_category_details_view.dart | 131 + lib/app/res/app_colors.dart | 72 + lib/app/res/app_dimensions.dart | 14 + lib/app/res/app_theme.dart | 204 + lib/app/res/suppoted_languages.dart | 13 + lib/app/routes/app_pages.dart | 507 ++ lib/app/routes/app_routes.dart | 147 + lib/main.dart | 201 +- pubspec.lock | 1514 ++++ pubspec.yaml | 91 +- test/widget_test.dart | 4 +- 488 files changed, 78858 insertions(+), 120 deletions(-) create mode 100644 .dart_tool/package_config.json create mode 100644 .dart_tool/package_graph.json create mode 100644 .dart_tool/version create mode 100644 .flutter-plugins-dependencies create mode 100644 .idea/.gitignore create mode 100644 .idea/caches/deviceStreaming.xml create mode 100644 .idea/libraries/Dart_Packages.xml create mode 100644 .idea/libraries/Dart_SDK.xml create mode 100644 .idea/libraries/Flutter_Plugins.xml create mode 100644 assets/.en create mode 100644 assets/uco/icons/arrow.svg create mode 100644 assets/uco/icons/aud_flag.png create mode 100644 assets/uco/icons/bankDetails.svg create mode 100644 assets/uco/icons/changePassoword.svg create mode 100644 assets/uco/icons/drop_down_ic.png create mode 100644 assets/uco/icons/euro_flag.png create mode 100644 assets/uco/icons/gbp_flag.png create mode 100644 assets/uco/icons/ic_QR.png create mode 100644 assets/uco/icons/ic_QR.svg create mode 100644 assets/uco/icons/ic_activation.svg create mode 100644 assets/uco/icons/ic_activity.svg create mode 100644 assets/uco/icons/ic_add.svg create mode 100644 assets/uco/icons/ic_add_new_Account.png create mode 100644 assets/uco/icons/ic_arrow_down.svg create mode 100644 assets/uco/icons/ic_arrow_down_icon.png create mode 100644 assets/uco/icons/ic_back_arrow_appbar.svg create mode 100644 assets/uco/icons/ic_back_white.svg create mode 100644 assets/uco/icons/ic_bank_transfer.svg create mode 100644 assets/uco/icons/ic_bill.svg create mode 100644 assets/uco/icons/ic_call.svg create mode 100644 assets/uco/icons/ic_camera.svg create mode 100644 assets/uco/icons/ic_camera_profile.svg create mode 100644 assets/uco/icons/ic_chat.svg create mode 100644 assets/uco/icons/ic_check_status.svg create mode 100644 assets/uco/icons/ic_cheque_deposit.svg create mode 100644 assets/uco/icons/ic_cheque_management.svg create mode 100644 assets/uco/icons/ic_chnage_pin.svg create mode 100644 assets/uco/icons/ic_client.png create mode 100644 assets/uco/icons/ic_client.svg create mode 100644 assets/uco/icons/ic_clock_circle.svg create mode 100644 assets/uco/icons/ic_congratulation.svg create mode 100644 assets/uco/icons/ic_congratulations!.svg create mode 100644 assets/uco/icons/ic_contact_us.png create mode 100644 assets/uco/icons/ic_contact_us.svg create mode 100644 assets/uco/icons/ic_credit.svg create mode 100644 assets/uco/icons/ic_credit_card_bills.svg create mode 100644 assets/uco/icons/ic_cross.svg create mode 100644 assets/uco/icons/ic_cross_option.svg create mode 100644 assets/uco/icons/ic_cross_white.svg create mode 100644 assets/uco/icons/ic_current_account_arrow.svg create mode 100644 assets/uco/icons/ic_customer_service.svg create mode 100644 assets/uco/icons/ic_cyber_security.svg create mode 100644 assets/uco/icons/ic_daily_transaction.svg create mode 100644 assets/uco/icons/ic_debit.svg create mode 100644 assets/uco/icons/ic_debit_card.svg create mode 100644 assets/uco/icons/ic_desposit_account_arrow.svg create mode 100644 assets/uco/icons/ic_device_management.svg create mode 100644 assets/uco/icons/ic_dollar_symbol.svg create mode 100644 assets/uco/icons/ic_download.svg create mode 100644 assets/uco/icons/ic_electricity.png create mode 100644 assets/uco/icons/ic_email.svg create mode 100644 assets/uco/icons/ic_filter_statement.svg create mode 100644 assets/uco/icons/ic_finger_print.svg create mode 100644 assets/uco/icons/ic_fingerprint.svg create mode 100644 assets/uco/icons/ic_gas.png create mode 100644 assets/uco/icons/ic_general_ledger.svg create mode 100644 assets/uco/icons/ic_government.png create mode 100644 assets/uco/icons/ic_holding_money.svg create mode 100644 assets/uco/icons/ic_home_icon.svg create mode 100644 assets/uco/icons/ic_internet.png create mode 100644 assets/uco/icons/ic_internet.svg create mode 100644 assets/uco/icons/ic_isb.png create mode 100644 assets/uco/icons/ic_karachi.png create mode 100644 assets/uco/icons/ic_kc.png create mode 100644 assets/uco/icons/ic_ke.png create mode 100644 assets/uco/icons/ic_khan.png create mode 100644 assets/uco/icons/ic_kprogresshud_spinner.png create mode 100644 assets/uco/icons/ic_kyc_unverified.svg create mode 100644 assets/uco/icons/ic_language.svg create mode 100644 assets/uco/icons/ic_link.png create mode 100644 assets/uco/icons/ic_location.svg create mode 100644 assets/uco/icons/ic_log_out.svg create mode 100644 assets/uco/icons/ic_logout.svg create mode 100644 assets/uco/icons/ic_manage_account.svg create mode 100644 assets/uco/icons/ic_menu_bar.svg create mode 100644 assets/uco/icons/ic_money_management.svg create mode 100644 assets/uco/icons/ic_multan.png create mode 100644 assets/uco/icons/ic_next.svg create mode 100644 assets/uco/icons/ic_notifactions.svg create mode 100644 assets/uco/icons/ic_notification_filter.svg create mode 100644 assets/uco/icons/ic_pakistan.png create mode 100644 assets/uco/icons/ic_person_setting.svg create mode 100644 assets/uco/icons/ic_phone.svg create mode 100644 assets/uco/icons/ic_phone_bottom_sheet.svg create mode 100644 assets/uco/icons/ic_qr_setting.svg create mode 100644 assets/uco/icons/ic_receiving_money.svg create mode 100644 assets/uco/icons/ic_request.svg create mode 100644 assets/uco/icons/ic_search.svg create mode 100644 assets/uco/icons/ic_security.png create mode 100644 assets/uco/icons/ic_select_contact.svg create mode 100644 assets/uco/icons/ic_setting.svg create mode 100644 assets/uco/icons/ic_share.svg create mode 100644 assets/uco/icons/ic_share_qr.svg create mode 100644 assets/uco/icons/ic_snding_money.svg create mode 100644 assets/uco/icons/ic_sort.png create mode 100644 assets/uco/icons/ic_stop.svg create mode 100644 assets/uco/icons/ic_sub_accounts.svg create mode 100644 assets/uco/icons/ic_tick.svg create mode 100644 assets/uco/icons/ic_tick_option.svg create mode 100644 assets/uco/icons/ic_u_cash.svg create mode 100644 assets/uco/icons/ic_u_receive_menu.svg create mode 100644 assets/uco/icons/ic_u_recive.svg create mode 100644 assets/uco/icons/ic_u_shop.svg create mode 100644 assets/uco/icons/ic_user.svg create mode 100644 assets/uco/icons/ic_utility_bills.svg create mode 100644 assets/uco/icons/ic_voice.svg create mode 100644 assets/uco/icons/ic_wallet.svg create mode 100644 assets/uco/icons/ic_warning.png create mode 100644 assets/uco/icons/ic_water.png create mode 100644 assets/uco/icons/ic_wise_card.svg create mode 100644 assets/uco/icons/ind_flag.png create mode 100644 assets/uco/icons/inviteFriendsUco.svg create mode 100644 assets/uco/icons/sending_icon.svg create mode 100644 assets/uco/icons/usa.png create mode 100644 assets/uco/icons/use_flag.png create mode 100644 assets/uco/images/im_qr.png create mode 100644 assets/uco/images/img_country_flag.png create mode 100644 assets/uco/images/img_country_flag.svg create mode 100644 assets/uco/images/img_debet.png create mode 100644 assets/uco/images/img_global.svg create mode 100644 assets/uco/images/img_intro_slider_1.png create mode 100644 assets/uco/images/img_intro_slider_2.png create mode 100644 assets/uco/images/img_round_dashboard_card.png create mode 100644 assets/uco/images/img_slider.svg create mode 100644 assets/uco/logo/ic_dashboard_logo.svg create mode 100644 assets/uco/logo/ic_launcher.png create mode 100644 assets/uco/logo/lg_back_arrow.svg create mode 100644 assets/uco/logo/lg_dialog_logo.svg create mode 100644 assets/uco/logo/lg_lunch_icon.svg create mode 100644 assets/uco/logo/lg_mfsys.png create mode 100644 assets/uco/logo/lg_uco_logo_white.svg create mode 100644 assets/uco/logo/shopping-cart.png create mode 100644 assets/uco/logo/uc-logo.png create mode 100644 assets/uco/logo/uc_logo.png create mode 100644 fonts/Inter-Black.ttf create mode 100644 fonts/Inter-Bold.ttf create mode 100644 fonts/Inter-ExtraBold.ttf create mode 100644 fonts/Inter-ExtraLight.ttf create mode 100644 fonts/Inter-Light.ttf create mode 100644 fonts/Inter-Medium.ttf create mode 100644 fonts/Inter-Regular.ttf create mode 100644 fonts/Inter-SemiBold.ttf create mode 100644 fonts/Inter-Thin.ttf create mode 100644 fonts/Poppins-Medium.ttf create mode 100644 fonts/Poppins-Regular.ttf create mode 100644 lib/app/bindings/dependency_injections.dart create mode 100644 lib/app/core/config/api_utils.dart create mode 100644 lib/app/core/config/connectivity_service.dart create mode 100644 lib/app/core/config/dio_exceptions.dart create mode 100644 lib/app/core/config/error_message_model.dart create mode 100644 lib/app/core/config/logging.dart create mode 100644 lib/app/core/config/requset_attr.dart create mode 100644 lib/app/core/config/server_request.dart create mode 100644 lib/app/core/config/server_response.dart create mode 100644 lib/app/core/constants/PinType.dart create mode 100644 lib/app/core/constants/api_keys.dart create mode 100644 lib/app/core/constants/app_assets.dart create mode 100644 lib/app/core/constants/app_contants.dart create mode 100644 lib/app/core/constants/form_field_constants.dart create mode 100644 lib/app/core/constants/translation_keys.dart create mode 100644 lib/app/core/constants/url_constants.dart create mode 100644 lib/app/core/constants/widget_types.dart create mode 100644 lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart create mode 100644 lib/app/core/data/repositories/app_repositories.dart create mode 100644 lib/app/core/dialogs/custom_loading.dart create mode 100644 lib/app/core/enums/api_keys.dart create mode 100644 lib/app/core/enums/countryCode.dart create mode 100644 lib/app/core/enums/http_methods.dart create mode 100644 lib/app/core/enums/languageCode.dart create mode 100644 lib/app/core/enums/request_constants.dart create mode 100644 lib/app/core/enums/screen_type.dart create mode 100644 lib/app/core/extensions/build_context_ext.dart create mode 100644 lib/app/core/local_stoarge/app_storage.dart create mode 100644 lib/app/core/utils/FingerPrintController.dart create mode 100644 lib/app/core/utils/SessionCache.dart create mode 100644 lib/app/core/utils/app_utils.dart create mode 100644 lib/app/core/utils/fields_utils.dart create mode 100644 lib/app/core/utils/globle_keys.dart create mode 100644 lib/app/core/utils/logs_utils.dart create mode 100644 lib/app/core/utils/phone_number_utils.dart create mode 100644 lib/app/core/utils/root_detector_device.dart create mode 100644 lib/app/core/utils/simulator_check.dart create mode 100644 lib/app/core/utils/url_encryption.dart create mode 100644 lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart create mode 100644 lib/app/custom_widgets/Fields/field_validations.dart create mode 100644 lib/app/custom_widgets/Fields/input_field.dart create mode 100644 lib/app/custom_widgets/bottom_sheet.dart create mode 100644 lib/app/custom_widgets/custom_app_bar.dart create mode 100644 lib/app/custom_widgets/custom_button.dart create mode 100644 lib/app/custom_widgets/custom_date_time_picker.dart create mode 100644 lib/app/custom_widgets/custom_dialog.dart create mode 100644 lib/app/custom_widgets/custom_dropdown.dart create mode 100644 lib/app/custom_widgets/custom_input_field.dart create mode 100644 lib/app/custom_widgets/custom_label.dart create mode 100644 lib/app/custom_widgets/custom_no_record.dart create mode 100644 lib/app/custom_widgets/custom_text.dart create mode 100644 lib/app/custom_widgets/custom_toasty.dart create mode 100644 lib/app/custom_widgets/date_picker.dart create mode 100644 lib/app/custom_widgets/pop_dialog.dart create mode 100644 lib/app/custom_widgets/responsive_widget.dart create mode 100644 lib/app/custom_widgets/widget_interactions.dart create mode 100644 lib/app/custom_widgets/widget_operation.dart create mode 100644 lib/app/l10n/Arabic.dart create mode 100644 lib/app/l10n/English.dart create mode 100644 lib/app/models/AccountInquiryResponseModel.dart create mode 100644 lib/app/models/AddNewAccountRequestModel.dart create mode 100644 lib/app/models/AuthenticationRequest.dart create mode 100644 lib/app/models/AuthenticationResponse.dart create mode 100644 lib/app/models/BeneficiaryAccountModel.dart create mode 100644 lib/app/models/Branch.dart create mode 100644 lib/app/models/ChangePasswordRequest.dart create mode 100644 lib/app/models/ChangeTransactionPinRequest.dart create mode 100644 lib/app/models/CreateTransactionPinOTPRequest.dart create mode 100644 lib/app/models/CreateTransactionPinRequest.dart create mode 100644 lib/app/models/DepositAccountResponse.dart create mode 100644 lib/app/models/DepositAccountTransaction.dart create mode 100644 lib/app/models/ExchangeRate.dart create mode 100644 lib/app/models/GLACCAddMoneyRequestModel.dart create mode 100644 lib/app/models/GenerateReportRequestModel.dart create mode 100644 lib/app/models/GlsResponseModel.dart create mode 100644 lib/app/models/LoginResponseModel.dart create mode 100644 lib/app/models/RefreshToken.dart create mode 100644 lib/app/models/RegisterRequest.dart create mode 100644 lib/app/models/SendTransactionStep1ResponseModel.dart create mode 100644 lib/app/models/SignupOtpRequest.dart create mode 100644 lib/app/models/SignupStep3RequestModel.dart create mode 100644 lib/app/models/SubmitTransactionRequestModel.dart create mode 100644 lib/app/models/SubmitTransactionResponseModel.dart create mode 100644 lib/app/models/TransactionHistoryRequest.dart create mode 100644 lib/app/models/TransactionPinRequestModel.dart create mode 100644 lib/app/models/TransactionPinResponseModel.dart create mode 100644 lib/app/models/TransactionRequestModel.dart create mode 100644 lib/app/models/TransactionResponseModel.dart create mode 100644 lib/app/models/TransactionSubmitRequestModel.dart create mode 100644 lib/app/models/TransactionSubmitResponseModel.dart create mode 100644 lib/app/models/UserActivity.dart create mode 100644 lib/app/models/UserActivityResponseModel.dart create mode 100644 lib/app/models/UserInfo.dart create mode 100644 lib/app/models/VerifyLoginOtpRequest.dart create mode 100644 lib/app/models/VerifySignupOtpRequest.dart create mode 100644 lib/app/models/ViewBalanceRequestModel.dart create mode 100644 lib/app/models/ViewBalanceResponseModel.dart create mode 100644 lib/app/models/accept_receive_transaction.dart create mode 100644 lib/app/models/accountStatementResponseModel.dart create mode 100644 lib/app/models/account_statment_model.dart create mode 100644 lib/app/models/chanange_password_params.dart create mode 100644 lib/app/models/create_transition_otp_model.dart create mode 100644 lib/app/models/dashboard_response_model.dart create mode 100644 lib/app/models/evaluated_cuency_model.dart create mode 100644 lib/app/models/finger_print_info.dart create mode 100644 lib/app/models/identity_drop_down_model.dart create mode 100644 lib/app/models/login_request_model.dart create mode 100644 lib/app/models/product_model.dart create mode 100644 lib/app/models/resen_ot_chanange_trans_pin.dart create mode 100644 lib/app/models/resend_ot_login_model.dart create mode 100644 lib/app/models/resend_otp_usend.dart create mode 100644 lib/app/models/reverse_transaction_model.dart create mode 100644 lib/app/models/u_recived_responce_model.dart create mode 100644 lib/app/models/upload_user_profile_model.dart create mode 100644 lib/app/modules/about_us/bindings/about_us_binding.dart create mode 100644 lib/app/modules/about_us/controllers/about_us_controller.dart create mode 100644 lib/app/modules/about_us/views/about_us_view.dart create mode 100644 lib/app/modules/account_statement/bindings/account_statement_binding.dart create mode 100644 lib/app/modules/account_statement/controllers/account_statement_controller.dart create mode 100644 lib/app/modules/account_statement/views/account_statement_view.dart create mode 100644 lib/app/modules/account_statement/views/shared/account_Statement_widget.dart create mode 100644 lib/app/modules/add_money/bindings/add_money_binding.dart create mode 100644 lib/app/modules/add_money/bindings/add_money_otp_binding.dart create mode 100644 lib/app/modules/add_money/bindings/payment_method_binding.dart create mode 100644 lib/app/modules/add_money/controllers/add_money_controller.dart create mode 100644 lib/app/modules/add_money/controllers/add_money_otp_controller.dart create mode 100644 lib/app/modules/add_money/controllers/payment_method_controller.dart create mode 100644 lib/app/modules/add_money/views/add_money_view.dart create mode 100644 lib/app/modules/add_money/views/shared/account_list_screen.dart create mode 100644 lib/app/modules/add_money/views/shared/currency_list_screen.dart create mode 100644 lib/app/modules/add_money/views/shared/otp_add_money.dart create mode 100644 lib/app/modules/add_money/views/shared/payment_method_view.dart create mode 100644 lib/app/modules/add_new_account/bindings/add_new_binding.dart create mode 100644 lib/app/modules/add_new_account/controllers/add_new_account_controller.dart create mode 100644 lib/app/modules/add_new_account/views/add_new_account_view.dart create mode 100644 lib/app/modules/agent_location/bindings/agent_location_binding.dart create mode 100644 lib/app/modules/agent_location/controllers/agent_location_controller.dart create mode 100644 lib/app/modules/agent_location/views/agent_location_view.dart create mode 100644 lib/app/modules/app_intro/bindings/intro_screen_binding.dart create mode 100644 lib/app/modules/app_intro/controllers/intro_screen_controller.dart create mode 100644 lib/app/modules/app_intro/views/intro_screen_view.dart create mode 100644 lib/app/modules/app_setting/bindings/app_setting_binding.dart create mode 100644 lib/app/modules/app_setting/controllers/app_setting_controller.dart create mode 100644 lib/app/modules/app_setting/views/app_setting_view.dart create mode 100644 lib/app/modules/app_setting/views/model/Language.dart create mode 100644 lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart create mode 100644 lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart create mode 100644 lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart create mode 100644 lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart create mode 100644 lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart create mode 100644 lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart create mode 100644 lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart create mode 100644 lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart create mode 100644 lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart create mode 100644 lib/app/modules/bill_management/bindings/bill_management_binding.dart create mode 100644 lib/app/modules/bill_management/controllers/bill_management_controller.dart create mode 100644 lib/app/modules/bill_management/views/bill_management_view.dart create mode 100644 lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart create mode 100644 lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart create mode 100644 lib/app/modules/bill_management_category/views/bill_management_category_view.dart create mode 100644 lib/app/modules/career/bindings/career_binding.dart create mode 100644 lib/app/modules/career/controllers/career_controller.dart create mode 100644 lib/app/modules/career/views/career_view.dart create mode 100644 lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart create mode 100644 lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart create mode 100644 lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart create mode 100644 lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart create mode 100644 lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart create mode 100644 lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart create mode 100644 lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart create mode 100644 lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart create mode 100644 lib/app/modules/cheque_activation/views/cheque_activation_view.dart create mode 100644 lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart create mode 100644 lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart create mode 100644 lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart create mode 100644 lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart create mode 100644 lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart create mode 100644 lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart create mode 100644 lib/app/modules/cheque_management/bindings/cheque_management_binding.dart create mode 100644 lib/app/modules/cheque_management/controllers/cheque_management_controller.dart create mode 100644 lib/app/modules/cheque_management/views/cheque_management_view.dart create mode 100644 lib/app/modules/cheque_request/bindings/cheque_request_binding.dart create mode 100644 lib/app/modules/cheque_request/controllers/cheque_request_controller.dart create mode 100644 lib/app/modules/cheque_request/views/cheque_request_view.dart create mode 100644 lib/app/modules/cheque_status/bindings/cheque_status_binding.dart create mode 100644 lib/app/modules/cheque_status/controllers/cheque_status_controller.dart create mode 100644 lib/app/modules/cheque_status/views/cheque_status_view.dart create mode 100644 lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart create mode 100644 lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart create mode 100644 lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart create mode 100644 lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart create mode 100644 lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart create mode 100644 lib/app/modules/contacts_screen/views/contacts_screen_view.dart create mode 100644 lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart create mode 100644 lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart create mode 100644 lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart create mode 100644 lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart create mode 100644 lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart create mode 100644 lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart create mode 100644 lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart create mode 100644 lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart create mode 100644 lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart create mode 100644 lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart create mode 100644 lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart create mode 100644 lib/app/modules/dashboard/views/dashboard_screen_view.dart create mode 100644 lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart create mode 100644 lib/app/modules/dashboard/views/shared/drawer_data.dart create mode 100644 lib/app/modules/dashboard/views/shared/home_page.dart create mode 100644 lib/app/modules/dashboard/views/shared/main_dash_board.dart create mode 100644 lib/app/modules/faqs/bindings/faqs_binding.dart create mode 100644 lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart create mode 100644 lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart create mode 100644 lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart create mode 100644 lib/app/modules/faqs/controllers/faqs_controller.dart create mode 100644 lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart create mode 100644 lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart create mode 100644 lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart create mode 100644 lib/app/modules/faqs/views/faqs_first_screen_view.dart create mode 100644 lib/app/modules/faqs/views/faqs_second_screen_view.dart create mode 100644 lib/app/modules/faqs/views/faqs_third_screen_view.dart create mode 100644 lib/app/modules/faqs/views/faqs_view.dart create mode 100644 lib/app/modules/faqs/views/model/FAQS.dart create mode 100644 lib/app/modules/general_ledger/bindings/general_ledger_binding.dart create mode 100644 lib/app/modules/general_ledger/controllers/general_ledger_controller.dart create mode 100644 lib/app/modules/general_ledger/views/general_ledger_view.dart create mode 100644 lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart create mode 100644 lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart create mode 100644 lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart create mode 100644 lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart create mode 100644 lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart create mode 100644 lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart create mode 100644 lib/app/modules/login/bindings/login_screen_binding.dart create mode 100644 lib/app/modules/login/controllers/login_screen_controller.dart create mode 100644 lib/app/modules/login/views/login_screen_view.dart create mode 100644 lib/app/modules/login/views/shared/bottom_sheet_login.dart create mode 100644 lib/app/modules/login/views/shared/expaanded_container.dart create mode 100644 lib/app/modules/login/views/shared/login_widget.dart create mode 100644 lib/app/modules/login/views/shared/top_dialog.dart create mode 100644 lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart create mode 100644 lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart create mode 100644 lib/app/modules/login_otp/views/o_t_p_screen_view.dart create mode 100644 lib/app/modules/my_account/bindings/my_account_binding.dart create mode 100644 lib/app/modules/my_account/controllers/my_account_controller.dart create mode 100644 lib/app/modules/my_account/views/my_account_view.dart create mode 100644 lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart create mode 100644 lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart create mode 100644 lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart create mode 100644 lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart create mode 100644 lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart create mode 100644 lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart create mode 100644 lib/app/modules/notifications/bindings/notifications_binding.dart create mode 100644 lib/app/modules/notifications/controllers/notifications_controller.dart create mode 100644 lib/app/modules/notifications/views/notifications_view.dart create mode 100644 lib/app/modules/password_change/bindings/password_change_binding.dart create mode 100644 lib/app/modules/password_change/controllers/password_change_controller.dart create mode 100644 lib/app/modules/password_change/views/password_change_view.dart create mode 100644 lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart create mode 100644 lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart create mode 100644 lib/app/modules/privacy_policy/views/privacy_policy_view.dart create mode 100644 lib/app/modules/qr_setting/bindings/qr_setting_binding.dart create mode 100644 lib/app/modules/qr_setting/controllers/qr_setting_controller.dart create mode 100644 lib/app/modules/qr_setting/views/qr_scan_screen.dart create mode 100644 lib/app/modules/qr_setting/views/qr_setting_view.dart create mode 100644 lib/app/modules/qr_setting/views/qr_view_screen.dart create mode 100644 lib/app/modules/qr_setting/views/scanner_buttons.dart create mode 100644 lib/app/modules/recipient_details/bindings/recipient_details_binding.dart create mode 100644 lib/app/modules/recipient_details/controllers/recipient_details_controller.dart create mode 100644 lib/app/modules/recipient_details/views/recipient_details_view.dart create mode 100644 lib/app/modules/sample_fields/bindings/sample_fields_binding.dart create mode 100644 lib/app/modules/sample_fields/controllers/sample_fields_controller.dart create mode 100644 lib/app/modules/sample_fields/views/sample_fields_view.dart create mode 100644 lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart create mode 100644 lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart create mode 100644 lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart create mode 100644 lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart create mode 100644 lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart create mode 100644 lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart create mode 100644 lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart create mode 100644 lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart create mode 100644 lib/app/modules/sign_up/views/shared/camera_screen.dart create mode 100644 lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart create mode 100644 lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart create mode 100644 lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart create mode 100644 lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart create mode 100644 lib/app/modules/speed_dial/src/simple_speed_dial.dart create mode 100644 lib/app/modules/splash/bindings/splash_screen_binding.dart create mode 100644 lib/app/modules/splash/controllers/splash_screen_controller.dart create mode 100644 lib/app/modules/splash/views/splash_screen_view.dart create mode 100644 lib/app/modules/transaction_history/bindings/transaction_history_binding.dart create mode 100644 lib/app/modules/transaction_history/controllers/transaction_history_controller.dart create mode 100644 lib/app/modules/transaction_history/shared/hository_list_widget.dart create mode 100644 lib/app/modules/transaction_history/views/transaction_history_view.dart create mode 100644 lib/app/modules/u_received/bindings/u_received_binding.dart create mode 100644 lib/app/modules/u_received/controllers/u_received_controller.dart create mode 100644 lib/app/modules/u_received/views/u_received_view.dart create mode 100644 lib/app/modules/u_send/bindings/u_send_binding.dart create mode 100644 lib/app/modules/u_send/controllers/u_send_controller.dart create mode 100644 lib/app/modules/u_send/views/u_send_view.dart create mode 100644 lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart create mode 100644 lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart create mode 100644 lib/app/modules/u_send_otp/views/u_send_otp_view.dart create mode 100644 lib/app/modules/user_activity/bindings/user_activity_binding.dart create mode 100644 lib/app/modules/user_activity/controllers/user_activity_controller.dart create mode 100644 lib/app/modules/user_activity/views/shared/date_time_dialog.dart create mode 100644 lib/app/modules/user_activity/views/user_activity_view.dart create mode 100644 lib/app/modules/user_activity/views/widgets/user_activity_widget.dart create mode 100644 lib/app/modules/user_profile/bindings/user_profile_binding.dart create mode 100644 lib/app/modules/user_profile/controllers/user_profile_controller.dart create mode 100644 lib/app/modules/user_profile/views/account_details_view.dart create mode 100644 lib/app/modules/user_profile/views/profile_details_view.dart create mode 100644 lib/app/modules/user_profile/views/user_profile_view.dart create mode 100644 lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart create mode 100644 lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart create mode 100644 lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart create mode 100644 lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart create mode 100644 lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart create mode 100644 lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart create mode 100644 lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart create mode 100644 lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart create mode 100644 lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart create mode 100644 lib/app/res/app_colors.dart create mode 100644 lib/app/res/app_dimensions.dart create mode 100644 lib/app/res/app_theme.dart create mode 100644 lib/app/res/suppoted_languages.dart create mode 100644 lib/app/routes/app_pages.dart create mode 100644 lib/app/routes/app_routes.dart create mode 100644 pubspec.lock diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json new file mode 100644 index 0000000..f15bca7 --- /dev/null +++ b/.dart_tool/package_config.json @@ -0,0 +1,1156 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "_fe_analyzer_shared", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-67.0.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "analyzer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-6.4.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "animated_toggle_switch", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/animated_toggle_switch-0.8.7", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "ansicolor", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ansicolor-2.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "archive", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/archive-3.6.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "args", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "asn1lib", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/asn1lib-1.6.5", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "async", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "auto_size_text", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/auto_size_text-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "back_button_interceptor", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/back_button_interceptor-7.0.3", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "boolean_selector", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "build", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/build-2.4.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "build_config", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "buttons_tabbar", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/buttons_tabbar-1.3.8", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "calendar_date_picker2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/calendar_date_picker2-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.16" + }, + { + "name": "camera", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera-0.10.6", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "camera_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_android-0.10.10+14", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "camera_avfoundation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_avfoundation-0.9.23+2", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "camera_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_platform_interface-2.12.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "camera_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_web-0.3.5+3", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "characters", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "checked_yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "chunked_stream", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/chunked_stream-1.4.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "circular_buffer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/circular_buffer-0.12.0", + "packageUri": "lib/", + "languageVersion": "2.13" + }, + { + "name": "clock", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "code_assets", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/code_assets-1.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "collection", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "connectivity_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/connectivity_plus-6.1.5", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "connectivity_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "convert", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "country_code_picker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/country_code_picker-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "cross_file", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/cross_file-0.3.5+2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "crypto", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "csv", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/csv-6.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "cupertino_icons", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "dart_console", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dart_console-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dart_style", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-2.3.6", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dbus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dbus-0.7.12", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "dcli", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "dcli_common", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_common-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dcli_core", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_core-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dcli_terminal", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_terminal-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "device_info_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/device_info_plus-10.1.2", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "device_info_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.3", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "dio", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dio-4.0.6", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "dropdown_button2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dropdown_button2-2.3.9", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "encrypt", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/encrypt-5.0.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "equatable", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/equatable-2.0.8", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "fake_async", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "ffi", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "file", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "fixnum", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "flutter", + "rootUri": "file:///C:/flutter/packages/flutter", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_camera_overlay_new", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_camera_overlay_new-0.0.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "flutter_contacts", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_contacts-1.1.9+2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_custom_clippers", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_custom_clippers-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_dotenv", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_dotenv-5.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_form_builder", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_form_builder-9.2.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "flutter_keyboard_visibility", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility-6.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_macos", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_platform_interface-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_lints", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-6.0.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_plugin_android_lifecycle", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.33", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_rounded_date_picker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_rounded_date_picker-3.0.4", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "flutter_svg", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_svg-2.2.3", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_test", + "rootUri": "file:///C:/flutter/packages/flutter_test", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_timer_countdown", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_timer_countdown-1.0.7", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_web_plugins", + "rootUri": "file:///C:/flutter/packages/flutter_web_plugins", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_zoom_drawer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_zoom_drawer-3.1.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "fluttertoast", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fluttertoast-8.2.14", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "functional_data", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/functional_data-1.2.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "get", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/get-4.6.6", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "get_cli", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/get_cli-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "getwidget", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/getwidget-4.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "glob", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "globbing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/globbing-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "google_fonts", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/google_fonts-7.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "hive", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hive-2.2.3", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "hive_flutter", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hive_flutter-1.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "hooks", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hooks-1.0.1", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "http", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "http_parser", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "image", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/image-4.3.0", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "ini", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ini-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "intl", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.19.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "introduction_slider", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/introduction_slider-2.0.1", + "packageUri": "lib/", + "languageVersion": "2.16" + }, + { + "name": "js", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "json2yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json2yaml-3.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "json_annotation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.8.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "json_serializable", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json_serializable-6.7.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "leak_tracker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_flutter_testing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_testing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "lints", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/lints-6.1.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "lists", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/lists-1.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "loader_overlay", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/loader_overlay-4.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "local_auth", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "local_auth_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_android-1.0.56", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "local_auth_darwin", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_darwin-1.6.1", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "local_auth_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_platform_interface-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "local_auth_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_windows-1.0.11", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "logging", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "matcher", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "material_color_utilities", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "meta", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.17.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "mime", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "mobile_scanner", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/mobile_scanner-6.0.11", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "native_synchronization_temp", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/native_synchronization_temp-0.7.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "native_toolchain_c", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/native_toolchain_c-0.17.4", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "nm", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/nm-0.5.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "objective_c", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/objective_c-9.3.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "package_config", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path_parsing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_parsing-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "path_provider", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "path_provider_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.22", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "path_provider_foundation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.6.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "path_provider_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "path_provider_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "path_provider_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "permission_handler", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler-11.3.0", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "permission_handler_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_android-12.1.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "permission_handler_apple", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_apple-9.4.7", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "permission_handler_html", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_html-0.1.3+5", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "permission_handler_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_platform_interface-4.3.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "permission_handler_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_windows-0.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "petitparser", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/petitparser-7.0.2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "pin_code_fields", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pin_code_fields-8.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "platform", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "plugin_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pointycastle", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pointycastle-3.9.1", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "posix", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/posix-6.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "process_run", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/process_run-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "pub_semver", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "pubspec_lock", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_lock-3.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "pubspec_manager", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_manager-1.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pubspec_parse", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "qr", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/qr-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "qr_flutter", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/qr_flutter-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "quickalert", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/quickalert-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "recase", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/recase-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "responsive_framework", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/responsive_framework-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "root_checker_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/root_checker_plus-0.0.7", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "scope", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/scope-5.1.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "screenshot", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/screenshot-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "settings_yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/settings_yaml-8.3.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "share_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/share_plus-12.0.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "share_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/share_plus_platform_interface-6.1.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "simple_speed_dial", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/simple_speed_dial-0.1.7", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "sky_engine", + "rootUri": "file:///C:/flutter/bin/cache/pkg/sky_engine", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "source_gen", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_gen-1.5.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "source_helper", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_helper-1.3.5", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "source_span", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "stack_trace", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "stream_channel", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "stream_transform", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "string_scanner", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "string_validator", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/string_validator-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "strings", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/strings-3.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "stylish_bottom_bar", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stylish_bottom_bar-1.0.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "sum_types", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/sum_types-0.3.5", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "synchronized", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/synchronized-3.4.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "system_info2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/system_info2-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "term_glyph", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "test_api", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.7", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "timer_count_down", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/timer_count_down-2.2.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "typed_data", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "unicode", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/unicode-0.3.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "url_launcher_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_linux-3.2.2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "url_launcher_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "url_launcher_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_web-2.4.2", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "url_launcher_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_windows-3.1.5", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "uuid", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/uuid-4.5.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "validators2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/validators2-5.1.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "vector_graphics", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics-1.1.19", + "packageUri": "lib/", + "languageVersion": "3.6" + }, + { + "name": "vector_graphics_codec", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_codec-1.1.13", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "vector_graphics_compiler", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_compiler-1.1.20", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "vector_math", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "version", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/version-3.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "vm_service", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.0.2", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "watcher", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "win32", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/win32-5.15.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "win32_registry", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/win32_registry-1.1.5", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "xdg_directories", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "xml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/xml-6.6.1", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "uco_mobile_poc", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "3.10" + } + ], + "generator": "pub", + "generatorVersion": "3.10.7", + "flutterRoot": "file:///C:/flutter", + "flutterVersion": "3.38.7", + "pubCache": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache" +} diff --git a/.dart_tool/package_graph.json b/.dart_tool/package_graph.json new file mode 100644 index 0000000..81c4321 --- /dev/null +++ b/.dart_tool/package_graph.json @@ -0,0 +1,1724 @@ +{ + "roots": [ + "uco_mobile_poc" + ], + "packages": [ + { + "name": "uco_mobile_poc", + "version": "1.0.0+1", + "dependencies": [ + "animated_toggle_switch", + "auto_size_text", + "buttons_tabbar", + "calendar_date_picker2", + "camera", + "connectivity_plus", + "country_code_picker", + "cupertino_icons", + "device_info_plus", + "dio", + "dropdown_button2", + "encrypt", + "flutter", + "flutter_camera_overlay_new", + "flutter_contacts", + "flutter_custom_clippers", + "flutter_dotenv", + "flutter_form_builder", + "flutter_keyboard_visibility", + "flutter_rounded_date_picker", + "flutter_svg", + "flutter_timer_countdown", + "flutter_zoom_drawer", + "fluttertoast", + "get", + "get_cli", + "getwidget", + "google_fonts", + "hive_flutter", + "image", + "introduction_slider", + "json_serializable", + "loader_overlay", + "local_auth", + "mobile_scanner", + "path_provider", + "permission_handler", + "pin_code_fields", + "pointycastle", + "qr_flutter", + "quickalert", + "responsive_framework", + "root_checker_plus", + "screenshot", + "share_plus", + "simple_speed_dial", + "string_validator", + "stylish_bottom_bar", + "timer_count_down" + ], + "devDependencies": [ + "flutter_lints", + "flutter_test" + ] + }, + { + "name": "flutter_lints", + "version": "6.0.0", + "dependencies": [ + "lints" + ] + }, + { + "name": "flutter_test", + "version": "0.0.0", + "dependencies": [ + "clock", + "collection", + "fake_async", + "flutter", + "leak_tracker_flutter_testing", + "matcher", + "meta", + "path", + "stack_trace", + "stream_channel", + "test_api", + "vector_math" + ] + }, + { + "name": "flutter_dotenv", + "version": "5.2.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "pointycastle", + "version": "3.9.1", + "dependencies": [ + "collection", + "convert", + "js" + ] + }, + { + "name": "encrypt", + "version": "5.0.3", + "dependencies": [ + "args", + "asn1lib", + "clock", + "collection", + "crypto", + "pointycastle" + ] + }, + { + "name": "root_checker_plus", + "version": "0.0.7", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "device_info_plus", + "version": "10.1.2", + "dependencies": [ + "device_info_plus_platform_interface", + "ffi", + "file", + "flutter", + "flutter_web_plugins", + "meta", + "web", + "win32", + "win32_registry" + ] + }, + { + "name": "get_cli", + "version": "1.9.1", + "dependencies": [ + "ansicolor", + "collection", + "dart_style", + "dcli", + "http", + "intl", + "meta", + "path", + "process_run", + "pub_semver", + "pubspec_parse", + "recase", + "version", + "yaml" + ] + }, + { + "name": "connectivity_plus", + "version": "6.1.5", + "dependencies": [ + "collection", + "connectivity_plus_platform_interface", + "flutter", + "flutter_web_plugins", + "meta", + "nm", + "web" + ] + }, + { + "name": "image", + "version": "4.3.0", + "dependencies": [ + "archive", + "meta", + "xml" + ] + }, + { + "name": "auto_size_text", + "version": "3.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "animated_toggle_switch", + "version": "0.8.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "flutter_keyboard_visibility", + "version": "6.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_linux", + "flutter_keyboard_visibility_macos", + "flutter_keyboard_visibility_platform_interface", + "flutter_keyboard_visibility_web", + "flutter_keyboard_visibility_windows", + "meta" + ] + }, + { + "name": "screenshot", + "version": "3.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "mobile_scanner", + "version": "6.0.11", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "plugin_platform_interface", + "web" + ] + }, + { + "name": "qr_flutter", + "version": "4.1.0", + "dependencies": [ + "flutter", + "qr" + ] + }, + { + "name": "path_provider", + "version": "2.1.3", + "dependencies": [ + "flutter", + "path_provider_android", + "path_provider_foundation", + "path_provider_linux", + "path_provider_platform_interface", + "path_provider_windows" + ] + }, + { + "name": "buttons_tabbar", + "version": "1.3.8", + "dependencies": [ + "flutter" + ] + }, + { + "name": "json_serializable", + "version": "6.7.1", + "dependencies": [ + "analyzer", + "async", + "build", + "build_config", + "collection", + "json_annotation", + "meta", + "path", + "pub_semver", + "pubspec_parse", + "source_gen", + "source_helper" + ] + }, + { + "name": "calendar_date_picker2", + "version": "1.0.2", + "dependencies": [ + "flutter", + "intl" + ] + }, + { + "name": "flutter_rounded_date_picker", + "version": "3.0.4", + "dependencies": [ + "flutter" + ] + }, + { + "name": "getwidget", + "version": "4.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "loader_overlay", + "version": "4.0.0", + "dependencies": [ + "back_button_interceptor", + "flutter" + ] + }, + { + "name": "country_code_picker", + "version": "3.0.0", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "string_validator", + "version": "1.0.2", + "dependencies": [] + }, + { + "name": "share_plus", + "version": "12.0.1", + "dependencies": [ + "cross_file", + "ffi", + "file", + "flutter", + "flutter_web_plugins", + "meta", + "mime", + "share_plus_platform_interface", + "url_launcher_linux", + "url_launcher_platform_interface", + "url_launcher_web", + "url_launcher_windows", + "web", + "win32" + ] + }, + { + "name": "dio", + "version": "4.0.6", + "dependencies": [ + "http_parser", + "path" + ] + }, + { + "name": "local_auth", + "version": "2.2.0", + "dependencies": [ + "flutter", + "local_auth_android", + "local_auth_darwin", + "local_auth_platform_interface", + "local_auth_windows" + ] + }, + { + "name": "responsive_framework", + "version": "1.4.0", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "flutter_svg", + "version": "2.2.3", + "dependencies": [ + "flutter", + "http", + "vector_graphics", + "vector_graphics_codec", + "vector_graphics_compiler" + ] + }, + { + "name": "flutter_camera_overlay_new", + "version": "0.0.1", + "dependencies": [ + "camera", + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "camera", + "version": "0.10.6", + "dependencies": [ + "camera_android", + "camera_avfoundation", + "camera_platform_interface", + "camera_web", + "flutter", + "flutter_plugin_android_lifecycle" + ] + }, + { + "name": "flutter_form_builder", + "version": "9.2.1", + "dependencies": [ + "flutter", + "intl" + ] + }, + { + "name": "permission_handler", + "version": "11.3.0", + "dependencies": [ + "flutter", + "meta", + "permission_handler_android", + "permission_handler_apple", + "permission_handler_html", + "permission_handler_platform_interface", + "permission_handler_windows" + ] + }, + { + "name": "flutter_contacts", + "version": "1.1.9+2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "dropdown_button2", + "version": "2.3.9", + "dependencies": [ + "flutter", + "meta" + ] + }, + { + "name": "stylish_bottom_bar", + "version": "1.0.3", + "dependencies": [ + "flutter" + ] + }, + { + "name": "simple_speed_dial", + "version": "0.1.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "quickalert", + "version": "1.0.2", + "dependencies": [ + "flutter", + "vector_math" + ] + }, + { + "name": "flutter_zoom_drawer", + "version": "3.1.2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "flutter_timer_countdown", + "version": "1.0.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "timer_count_down", + "version": "2.2.2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "pin_code_fields", + "version": "8.0.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "fluttertoast", + "version": "8.2.14", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "web" + ] + }, + { + "name": "flutter_custom_clippers", + "version": "2.1.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "introduction_slider", + "version": "2.0.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "hive_flutter", + "version": "1.1.0", + "dependencies": [ + "flutter", + "hive", + "path", + "path_provider" + ] + }, + { + "name": "google_fonts", + "version": "7.0.0", + "dependencies": [ + "crypto", + "flutter", + "http", + "path_provider" + ] + }, + { + "name": "get", + "version": "4.6.6", + "dependencies": [ + "flutter" + ] + }, + { + "name": "cupertino_icons", + "version": "1.0.8", + "dependencies": [] + }, + { + "name": "flutter", + "version": "0.0.0", + "dependencies": [ + "characters", + "collection", + "material_color_utilities", + "meta", + "sky_engine", + "vector_math" + ] + }, + { + "name": "lints", + "version": "6.1.0", + "dependencies": [] + }, + { + "name": "stream_channel", + "version": "2.1.4", + "dependencies": [ + "async" + ] + }, + { + "name": "meta", + "version": "1.17.0", + "dependencies": [] + }, + { + "name": "collection", + "version": "1.19.1", + "dependencies": [] + }, + { + "name": "leak_tracker_flutter_testing", + "version": "3.0.10", + "dependencies": [ + "flutter", + "leak_tracker", + "leak_tracker_testing", + "matcher", + "meta" + ] + }, + { + "name": "vector_math", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "stack_trace", + "version": "1.12.1", + "dependencies": [ + "path" + ] + }, + { + "name": "clock", + "version": "1.1.2", + "dependencies": [] + }, + { + "name": "fake_async", + "version": "1.3.3", + "dependencies": [ + "clock", + "collection" + ] + }, + { + "name": "path", + "version": "1.9.1", + "dependencies": [] + }, + { + "name": "matcher", + "version": "0.12.17", + "dependencies": [ + "async", + "meta", + "stack_trace", + "term_glyph", + "test_api" + ] + }, + { + "name": "test_api", + "version": "0.7.7", + "dependencies": [ + "async", + "boolean_selector", + "collection", + "meta", + "source_span", + "stack_trace", + "stream_channel", + "string_scanner", + "term_glyph" + ] + }, + { + "name": "js", + "version": "0.7.2", + "dependencies": [] + }, + { + "name": "convert", + "version": "3.1.2", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "crypto", + "version": "3.0.7", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "asn1lib", + "version": "1.6.5", + "dependencies": [] + }, + { + "name": "args", + "version": "2.7.0", + "dependencies": [] + }, + { + "name": "plugin_platform_interface", + "version": "2.1.8", + "dependencies": [ + "meta" + ] + }, + { + "name": "win32_registry", + "version": "1.1.5", + "dependencies": [ + "ffi", + "win32" + ] + }, + { + "name": "win32", + "version": "5.15.0", + "dependencies": [ + "ffi" + ] + }, + { + "name": "web", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "flutter_web_plugins", + "version": "0.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "file", + "version": "7.0.1", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "ffi", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "device_info_plus_platform_interface", + "version": "7.0.3", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "yaml", + "version": "3.1.3", + "dependencies": [ + "collection", + "source_span", + "string_scanner" + ] + }, + { + "name": "version", + "version": "3.0.2", + "dependencies": [] + }, + { + "name": "recase", + "version": "4.1.0", + "dependencies": [] + }, + { + "name": "pub_semver", + "version": "2.2.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "pubspec_parse", + "version": "1.4.0", + "dependencies": [ + "checked_yaml", + "collection", + "json_annotation", + "pub_semver", + "yaml" + ] + }, + { + "name": "process_run", + "version": "1.3.0", + "dependencies": [ + "args", + "collection", + "meta", + "path", + "pub_semver", + "string_scanner", + "synchronized", + "yaml" + ] + }, + { + "name": "intl", + "version": "0.19.0", + "dependencies": [ + "clock", + "meta", + "path" + ] + }, + { + "name": "http", + "version": "1.6.0", + "dependencies": [ + "async", + "http_parser", + "meta", + "web" + ] + }, + { + "name": "dcli", + "version": "6.1.2", + "dependencies": [ + "archive", + "args", + "async", + "chunked_stream", + "collection", + "convert", + "crypto", + "csv", + "dart_console", + "dcli_common", + "dcli_core", + "dcli_terminal", + "equatable", + "ffi", + "file", + "glob", + "ini", + "logging", + "meta", + "mime", + "native_synchronization_temp", + "path", + "posix", + "pub_semver", + "pubspec_lock", + "pubspec_manager", + "scope", + "settings_yaml", + "stack_trace", + "system_info2", + "uuid", + "validators2", + "win32", + "yaml" + ] + }, + { + "name": "dart_style", + "version": "2.3.6", + "dependencies": [ + "analyzer", + "args", + "collection", + "path", + "pub_semver", + "source_span" + ] + }, + { + "name": "ansicolor", + "version": "2.0.3", + "dependencies": [] + }, + { + "name": "nm", + "version": "0.5.0", + "dependencies": [ + "dbus" + ] + }, + { + "name": "connectivity_plus_platform_interface", + "version": "2.0.1", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "xml", + "version": "6.6.1", + "dependencies": [ + "collection", + "meta", + "petitparser" + ] + }, + { + "name": "archive", + "version": "3.6.1", + "dependencies": [ + "crypto", + "path" + ] + }, + { + "name": "flutter_keyboard_visibility_windows", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_web", + "version": "2.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface", + "flutter_web_plugins" + ] + }, + { + "name": "flutter_keyboard_visibility_macos", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_linux", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_platform_interface", + "version": "2.0.0", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "qr", + "version": "3.0.2", + "dependencies": [ + "meta" + ] + }, + { + "name": "path_provider_windows", + "version": "2.3.0", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface" + ] + }, + { + "name": "path_provider_platform_interface", + "version": "2.1.2", + "dependencies": [ + "flutter", + "platform", + "plugin_platform_interface" + ] + }, + { + "name": "path_provider_linux", + "version": "2.2.1", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface", + "xdg_directories" + ] + }, + { + "name": "path_provider_foundation", + "version": "2.6.0", + "dependencies": [ + "ffi", + "flutter", + "objective_c", + "path_provider_platform_interface" + ] + }, + { + "name": "path_provider_android", + "version": "2.2.22", + "dependencies": [ + "flutter", + "path_provider_platform_interface" + ] + }, + { + "name": "source_helper", + "version": "1.3.5", + "dependencies": [ + "analyzer", + "collection", + "source_gen" + ] + }, + { + "name": "source_gen", + "version": "1.5.0", + "dependencies": [ + "analyzer", + "async", + "build", + "dart_style", + "glob", + "path", + "source_span", + "yaml" + ] + }, + { + "name": "json_annotation", + "version": "4.8.1", + "dependencies": [ + "meta" + ] + }, + { + "name": "build_config", + "version": "1.2.0", + "dependencies": [ + "checked_yaml", + "json_annotation", + "path", + "pubspec_parse" + ] + }, + { + "name": "build", + "version": "2.4.1", + "dependencies": [ + "analyzer", + "async", + "convert", + "crypto", + "glob", + "logging", + "meta", + "package_config", + "path" + ] + }, + { + "name": "async", + "version": "2.13.0", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "analyzer", + "version": "6.4.1", + "dependencies": [ + "_fe_analyzer_shared", + "collection", + "convert", + "crypto", + "glob", + "meta", + "package_config", + "path", + "pub_semver", + "source_span", + "watcher", + "yaml" + ] + }, + { + "name": "back_button_interceptor", + "version": "7.0.3", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "url_launcher_platform_interface", + "version": "2.3.2", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "url_launcher_linux", + "version": "3.2.2", + "dependencies": [ + "flutter", + "url_launcher_platform_interface" + ] + }, + { + "name": "url_launcher_windows", + "version": "3.1.5", + "dependencies": [ + "flutter", + "url_launcher_platform_interface" + ] + }, + { + "name": "url_launcher_web", + "version": "2.4.2", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "url_launcher_platform_interface", + "web" + ] + }, + { + "name": "share_plus_platform_interface", + "version": "6.1.0", + "dependencies": [ + "cross_file", + "flutter", + "meta", + "mime", + "path_provider", + "plugin_platform_interface", + "uuid" + ] + }, + { + "name": "mime", + "version": "2.0.0", + "dependencies": [] + }, + { + "name": "cross_file", + "version": "0.3.5+2", + "dependencies": [ + "meta", + "web" + ] + }, + { + "name": "http_parser", + "version": "4.1.2", + "dependencies": [ + "collection", + "source_span", + "string_scanner", + "typed_data" + ] + }, + { + "name": "local_auth_windows", + "version": "1.0.11", + "dependencies": [ + "flutter", + "local_auth_platform_interface" + ] + }, + { + "name": "local_auth_platform_interface", + "version": "1.1.0", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "local_auth_darwin", + "version": "1.6.1", + "dependencies": [ + "flutter", + "intl", + "local_auth_platform_interface" + ] + }, + { + "name": "local_auth_android", + "version": "1.0.56", + "dependencies": [ + "flutter", + "flutter_plugin_android_lifecycle", + "intl", + "local_auth_platform_interface" + ] + }, + { + "name": "vector_graphics_compiler", + "version": "1.1.20", + "dependencies": [ + "args", + "meta", + "path", + "path_parsing", + "vector_graphics_codec", + "xml" + ] + }, + { + "name": "vector_graphics_codec", + "version": "1.1.13", + "dependencies": [] + }, + { + "name": "vector_graphics", + "version": "1.1.19", + "dependencies": [ + "flutter", + "http", + "vector_graphics_codec" + ] + }, + { + "name": "flutter_plugin_android_lifecycle", + "version": "2.0.33", + "dependencies": [ + "flutter" + ] + }, + { + "name": "camera_web", + "version": "0.3.5+3", + "dependencies": [ + "camera_platform_interface", + "flutter", + "flutter_web_plugins", + "stream_transform", + "web" + ] + }, + { + "name": "camera_platform_interface", + "version": "2.12.0", + "dependencies": [ + "cross_file", + "flutter", + "plugin_platform_interface", + "stream_transform" + ] + }, + { + "name": "camera_avfoundation", + "version": "0.9.23+2", + "dependencies": [ + "camera_platform_interface", + "flutter", + "stream_transform" + ] + }, + { + "name": "camera_android", + "version": "0.10.10+14", + "dependencies": [ + "camera_platform_interface", + "flutter", + "flutter_plugin_android_lifecycle", + "stream_transform" + ] + }, + { + "name": "permission_handler_platform_interface", + "version": "4.3.0", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "permission_handler_windows", + "version": "0.2.1", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "permission_handler_html", + "version": "0.1.3+5", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "permission_handler_platform_interface", + "web" + ] + }, + { + "name": "permission_handler_apple", + "version": "9.4.7", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "permission_handler_android", + "version": "12.1.0", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "hive", + "version": "2.2.3", + "dependencies": [ + "crypto", + "meta" + ] + }, + { + "name": "sky_engine", + "version": "0.0.0", + "dependencies": [] + }, + { + "name": "material_color_utilities", + "version": "0.11.1", + "dependencies": [ + "collection" + ] + }, + { + "name": "characters", + "version": "1.4.0", + "dependencies": [] + }, + { + "name": "leak_tracker_testing", + "version": "3.0.2", + "dependencies": [ + "leak_tracker", + "matcher", + "meta" + ] + }, + { + "name": "leak_tracker", + "version": "11.0.2", + "dependencies": [ + "clock", + "collection", + "meta", + "path", + "vm_service" + ] + }, + { + "name": "term_glyph", + "version": "1.2.2", + "dependencies": [] + }, + { + "name": "string_scanner", + "version": "1.4.1", + "dependencies": [ + "source_span" + ] + }, + { + "name": "source_span", + "version": "1.10.2", + "dependencies": [ + "collection", + "path", + "term_glyph" + ] + }, + { + "name": "boolean_selector", + "version": "2.1.2", + "dependencies": [ + "source_span", + "string_scanner" + ] + }, + { + "name": "typed_data", + "version": "1.4.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "checked_yaml", + "version": "2.0.4", + "dependencies": [ + "json_annotation", + "source_span", + "yaml" + ] + }, + { + "name": "synchronized", + "version": "3.4.0", + "dependencies": [] + }, + { + "name": "validators2", + "version": "5.1.0", + "dependencies": [] + }, + { + "name": "uuid", + "version": "4.5.2", + "dependencies": [ + "crypto", + "fixnum", + "meta" + ] + }, + { + "name": "system_info2", + "version": "4.1.0", + "dependencies": [ + "globbing", + "path" + ] + }, + { + "name": "settings_yaml", + "version": "8.3.1", + "dependencies": [ + "collection", + "meta", + "path", + "uuid", + "yaml" + ] + }, + { + "name": "scope", + "version": "5.1.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "pubspec_manager", + "version": "1.0.3", + "dependencies": [ + "meta", + "path", + "pub_semver", + "strings" + ] + }, + { + "name": "pubspec_lock", + "version": "3.0.2", + "dependencies": [ + "functional_data", + "json2yaml", + "meta", + "sum_types", + "yaml" + ] + }, + { + "name": "posix", + "version": "6.0.3", + "dependencies": [ + "ffi", + "meta", + "path" + ] + }, + { + "name": "native_synchronization_temp", + "version": "0.7.1", + "dependencies": [ + "ffi" + ] + }, + { + "name": "logging", + "version": "1.3.0", + "dependencies": [] + }, + { + "name": "ini", + "version": "2.1.0", + "dependencies": [] + }, + { + "name": "glob", + "version": "2.1.3", + "dependencies": [ + "async", + "collection", + "file", + "path", + "string_scanner" + ] + }, + { + "name": "equatable", + "version": "2.0.8", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "dcli_terminal", + "version": "6.1.2", + "dependencies": [ + "dart_console" + ] + }, + { + "name": "dcli_core", + "version": "6.1.2", + "dependencies": [ + "async", + "circular_buffer", + "collection", + "crypto", + "dcli_common", + "ffi", + "logging", + "meta", + "path", + "scope", + "stack_trace", + "uuid" + ] + }, + { + "name": "dcli_common", + "version": "6.1.2", + "dependencies": [ + "meta", + "path", + "scope" + ] + }, + { + "name": "dart_console", + "version": "4.1.2", + "dependencies": [ + "characters", + "ffi", + "intl", + "win32" + ] + }, + { + "name": "csv", + "version": "6.0.0", + "dependencies": [] + }, + { + "name": "chunked_stream", + "version": "1.4.2", + "dependencies": [ + "meta" + ] + }, + { + "name": "dbus", + "version": "0.7.12", + "dependencies": [ + "args", + "ffi", + "meta", + "xml" + ] + }, + { + "name": "petitparser", + "version": "7.0.2", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "platform", + "version": "3.1.6", + "dependencies": [] + }, + { + "name": "xdg_directories", + "version": "1.1.0", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "objective_c", + "version": "9.3.0", + "dependencies": [ + "code_assets", + "collection", + "ffi", + "hooks", + "logging", + "native_toolchain_c", + "pub_semver" + ] + }, + { + "name": "package_config", + "version": "2.2.0", + "dependencies": [ + "path" + ] + }, + { + "name": "watcher", + "version": "1.2.1", + "dependencies": [ + "async", + "path" + ] + }, + { + "name": "_fe_analyzer_shared", + "version": "67.0.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "path_parsing", + "version": "1.1.0", + "dependencies": [ + "meta", + "vector_math" + ] + }, + { + "name": "stream_transform", + "version": "2.1.1", + "dependencies": [] + }, + { + "name": "vm_service", + "version": "15.0.2", + "dependencies": [] + }, + { + "name": "fixnum", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "globbing", + "version": "1.0.0", + "dependencies": [ + "path" + ] + }, + { + "name": "strings", + "version": "3.1.2", + "dependencies": [ + "characters", + "unicode" + ] + }, + { + "name": "sum_types", + "version": "0.3.5", + "dependencies": [ + "meta" + ] + }, + { + "name": "json2yaml", + "version": "3.0.1", + "dependencies": [ + "meta" + ] + }, + { + "name": "functional_data", + "version": "1.2.0", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "circular_buffer", + "version": "0.12.0", + "dependencies": [] + }, + { + "name": "native_toolchain_c", + "version": "0.17.4", + "dependencies": [ + "code_assets", + "glob", + "hooks", + "logging", + "meta", + "pub_semver" + ] + }, + { + "name": "hooks", + "version": "1.0.1", + "dependencies": [ + "collection", + "crypto", + "logging", + "meta", + "pub_semver", + "yaml" + ] + }, + { + "name": "code_assets", + "version": "1.0.0", + "dependencies": [ + "collection", + "hooks" + ] + }, + { + "name": "unicode", + "version": "0.3.1", + "dependencies": [ + "lists" + ] + }, + { + "name": "lists", + "version": "1.0.1", + "dependencies": [ + "meta" + ] + } + ], + "configVersion": 1 +} \ No newline at end of file diff --git a/.dart_tool/version b/.dart_tool/version new file mode 100644 index 0000000..6a20a82 --- /dev/null +++ b/.dart_tool/version @@ -0,0 +1 @@ +3.38.7 \ No newline at end of file diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 0000000..483ad75 --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera_avfoundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_avfoundation-0.9.23+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_contacts","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_contacts-1.1.9+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility-6.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_darwin-1.6.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.6.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_apple","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_apple-9.4.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"root_checker_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\root_checker_plus-0.0.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"camera_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_android-0.10.10+14\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_contacts","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_contacts-1.1.9+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility-6.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_plugin_android_lifecycle-2.0.33\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_android-1.0.56\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_android-12.1.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"root_checker_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\root_checker_plus-0.0.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_macos","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_macos-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_darwin-1.6.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.6.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_linux","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_linux-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":false,"dependencies":["url_launcher_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_linux-3.2.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_windows-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_windows-1.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_windows-0.2.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":["url_launcher_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_windows-3.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"camera_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_web-0.3.5+3\\\\","dependencies":[],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_web-2.0.0\\\\","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","dependencies":[],"dev_dependency":false},{"name":"permission_handler_html","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_html-0.1.3+5\\\\","dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","dependencies":["url_launcher_web"],"dev_dependency":false},{"name":"url_launcher_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_web-2.4.2\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"camera","dependencies":["camera_android","camera_avfoundation","camera_web","flutter_plugin_android_lifecycle"]},{"name":"camera_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"camera_avfoundation","dependencies":[]},{"name":"camera_web","dependencies":[]},{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"flutter_camera_overlay_new","dependencies":["camera"]},{"name":"flutter_contacts","dependencies":[]},{"name":"flutter_keyboard_visibility","dependencies":["flutter_keyboard_visibility_linux","flutter_keyboard_visibility_macos","flutter_keyboard_visibility_web","flutter_keyboard_visibility_windows"]},{"name":"flutter_keyboard_visibility_linux","dependencies":[]},{"name":"flutter_keyboard_visibility_macos","dependencies":[]},{"name":"flutter_keyboard_visibility_web","dependencies":[]},{"name":"flutter_keyboard_visibility_windows","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"fluttertoast","dependencies":[]},{"name":"local_auth","dependencies":["local_auth_android","local_auth_darwin","local_auth_windows"]},{"name":"local_auth_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"local_auth_darwin","dependencies":[]},{"name":"local_auth_windows","dependencies":[]},{"name":"mobile_scanner","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"root_checker_plus","dependencies":[]},{"name":"share_plus","dependencies":["url_launcher_web","url_launcher_windows","url_launcher_linux"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2026-02-19 10:21:40.359562","version":"3.38.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..04b285e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,19 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Flutter +.dart_tool/ +build/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ + +# Android +android/.gradle/ +android/local.properties + +# iOS +ios/Pods/ +ios/.symlinks/ diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml new file mode 100644 index 0000000..5c94783 --- /dev/null +++ b/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1414 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 0000000..0442d0e --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,1532 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml new file mode 100644 index 0000000..0218bad --- /dev/null +++ b/.idea/libraries/Dart_SDK.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml new file mode 100644 index 0000000..b4235ba --- /dev/null +++ b/.idea/libraries/Flutter_Plugins.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 4c38193..f4fe1c8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,5 @@ - - + \ No newline at end of file diff --git a/.idea/uco-mobile-poc.iml b/.idea/uco-mobile-poc.iml index d6ebd48..d327551 100644 --- a/.idea/uco-mobile-poc.iml +++ b/.idea/uco-mobile-poc.iml @@ -2,8 +2,15 @@ - + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index bdbb48d..46c390f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -16,9 +16,9 @@ - + { + "associatedIndex": 8 +} ", + "io.flutter.project.isFirstOpen": "true", + "io.flutter.reload.alreadyRun": "true", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Users/samanwaqar/Documents/GitHub/uco-mobile-poc", + "project.structure.last.edited": "Project", + "project.structure.proportion": "0.0", + "project.structure.side.proportion": "0.2", + "settings.editor.selected.configurable": "configurable.group.build", "show.migrate.to.gradle.popup": "false" } }]]> + + + + + + + + + + diff --git a/assets/.en b/assets/.en new file mode 100644 index 0000000..e69de29 diff --git a/assets/uco/icons/arrow.svg b/assets/uco/icons/arrow.svg new file mode 100644 index 0000000..711df5c --- /dev/null +++ b/assets/uco/icons/arrow.svg @@ -0,0 +1,94 @@ + + + + + + + diff --git a/assets/uco/icons/aud_flag.png b/assets/uco/icons/aud_flag.png new file mode 100644 index 0000000000000000000000000000000000000000..fdf4da06afb51db64c4aad224978e254f32b6e59 GIT binary patch literal 9757 zcmV+&CgRzNP)@~0drDELIAGL9O(c600d`2O+f$vv5yPNAVLd=ZL=XjG!HZi(xddEU*IifF zRZ$Tkh_FBc;YJh*M-Cw54oN06)BU~GIY=@`riaO767qYV$z-Ox=jf@fs<*1%dO6%8 zd>J3_r_IS}1&wb%omdj3Tl8k6XPZdBN1pv5EGJLzFLF?D;M&wYij!^}RObMN0nlVZ zftrzCUaHvABgY2u=@&SqUSG9cVPpzIp+LZb1<=OE zO3xXLOiw_|#6iOzsbQCJSc2n~Ozm`IZ_tg0;$c!jUP?jmircc26Ab$}QQUFq@Z>#c z0yJ6;;~(>;uLs9>2d5Z+Uwp(PvnTiR=Q$3g$;rr?GY6uMuAHyED8acQ% zo_?YmyuDN?*}E4xOP9iwn_J@;-p2{or;-TlKb@9Ew!Gehh#r}cn0uYiwQg|H9Sz+=Dwi?1(;B4S-;l5E34NaaN12GLNu zCGF^6(&47KrPI4BD#|bTyC0@Q#B{Za_gCfdHMWl)-UbN|canrfGDGjY1JP)N!b1lg zJIJd{4;3>#L2tihRalHB0q=Zx3|TpPxC6}nZX|W+;2{VhAOr(CK^-TzVbeCD+-P647eS z8h8yKZt;Ccv#i{30`G4*1yK~?W<;?e{UT^u>(|3GKHlQ{kgzOVaTqH% zo`8G9MX^BPlCZc>QbYQDFbZx$gZnVMf`g-=(QJaz7+?7u3xc8bu3c68oV!$rZxSy^ zW{5P)^`C!6@ds<6%gKR8UsAOn2}{tjWmYvyr5RfD@o9I|EVdC%|1ud(FI_&8a2^dv zg9^;f4xOfPCD&hPzg`WEQd?m13d*2kf`YH$6FFB^rnZ5g5`coJzBaMbzUhZLcjbm6ZN=4vJ~dKv7y! z<9X67!Ryvpb#TjtC4~vguV@NzLg@*UAdbvTnREdz#^pZDjt-rsL#a%$CM?z{IC>h& zIkU}#g)|G9A*(}YLBu<2k7MJfXV6p-d2M%IsZEZES^FehjLS3(4V8J5X}%x`&)2nY zO%21thq)VB4?PG~e$5E3J!a^ytB+vq*2ZjxY{Al<5SEn+8H;icy_^ph;1Ug!a{4qg zLF!%h2upPYmMxBmiiEdOZze2chQhXPwJ9u%m>Fui!a{KD2UN`TPXQJdB=daPARd5hgDhq*VW`;sO{Lt#qnKaAd zcaPxxk55T4m&QhHk3ftW)d3C=#cRFxgvD+ci+ZHq1m^U~GjmvOWOMByvn|M>YQb(g z&a!JIjfR-8c-(oX#qA_4%hsQ0)MjW%|425`fFetmVD(r-VKZW+g#KGPES6b+55lwMVB)caC-ZbdUWbqqP*tK63UPeL~P#< zWw>>}uCUmE_`adiO%9W1|11RtT}er)5i1w;LzzLqm*1r#>G(C2lo-*kPY@!*b<#dV z2ZZ53N|yA0yC@%wyeoofpAbAhe?PKw?Krm_zc@T*lPT>`!dq}6P8FCxPM)04vaJgc z6kvDgom^VVFxt9q6n@OA`PsH?zB)Df#RNevEWrs^qc1aI#rk9TcFS;#9?=GuGOuIn zmuJzX{f+N<-;fCWo?3th?v6lwzw(P<>AK@cWoZ(75qb5Sp>ZFXGLj}Ng_Cev9OmTl zGjp|CezCRf8Ta20W1;z%B{Ni8Sa=T)wEg{exPpc(pqe$MC#FyAZr8rM_h(?t^xY2S zz(iBYa~X#xy$2`Yl*=oXjfQLqi#5o>t;-@eWtOc!j{PZD>)cOYCg8PYha66ratiIc z;c@H7zzN*6!0g_4tVfyAuvyMAq}F_4-NC(85SgR?)%Lp6LEj}_LdKP1I1a~R!k+Jj z^jY5pH_1(zq+OjmM`>EM+QmjNQFZN0^(#U}B|o`!Ha!xahu6@da0R0-+=aA4*XLjr zEc5>M+}rWcut;b$iaPgCIhl=T=IzDB^ddNpcwR*Qof%2bT!Mo*e5NQj#3EydVKTOn za~zF?0)d7v#HrxPb_;Q#Lp|L*w6PBb1Y7Bh!A zntO8GB(X%ITw$T>i2Rl&Io;9@Xhb$|QT6N&&d^%f(E4)I688trCjn#wiH7vHC1!HPo^VL(W$dNk&o_RZkvO;Psl zZhtOGt6jkv46;O>OpyQIG*? z7g<4?W?X_=ZHM>4DFZ!~yv?aVR!2$S#Xl6qpFc7lsyfYD4LsQXDusFWRVcK-QjD4c zQBS&NoX0ccx?#nJ<8|)Gaf)Y{mRV`71E^Jj37q%BIB$Jn6l4+*)*9Y^=7Z^s(W7C= z$gt-nz-csS{r&fF1tn9G*dN!{^tu`viB0} z_(y~$u(1~8pirvOA}Yf2My35BABt?MB4wvJ9D_TArp}|o+rWnj&BOP$!J5CFs`~)W zV_tmxg4KzM3yiflSu|`Zhfa)_JNb<8_iuq_8jgqViA49#El@j?aPQ#q*%m_v)SOX4 z?NhpS^vAbhC?e{Pf zm=h;{i`J^SevpZWhYkuwbBeJc*}Xp#>p%S!GbVM%9kH!oFbMeld;vVQC^qjjLP3q z^ReO6->kltsM0>n?raOprSu}Haq^vU!5Dgnbzv#lwF|{RmUlo`DU>J-3Iq+D75@Hc zF>@w(?|Q1^sQo$i?nS{r|7rF-jkH?6^b#gM-U)k?F5~Fw9NY@fl;K&658$&kcS-#K zZS6N>!G5VI%Nhz1Pqesw^}?J3)2dc#sUa}ou}g=ud}$Q5Hl+^R)`X>a+csn`T?$bs z&#scID+!CQFM>C2beXUa9{u~{`cFS0Z=HE9Q0d{r2><+Z{CnNqc;u-cZwa9xtwQxR zm1f8qRMi*TD-g$i&9+)RDRPPstzJhn?W(j)4W~ok6n`4YoS|2y_O>c4*Vzw{vwV4# zun;sEjc39V_T`uG=-XG4UMl`^7In4l2zc!^_&#agy{qikUvcUF`=Kf+#Mae=r4!VY zp?TRG-ySH{2h%hbTX^eKc>RSw_<~(bZ6mA~p>RrNjT2i#V20iiJaXoQo>o;^$m3*HLt+~CAHIrHzvW54hb71yojI3}PgCapBGt|| z1yW9AOSjtW`fLO`wDC22zNpxMyB_}*_97@fN1(!wsnReyohr`K&X&xObfAX^S}uMA zx^CU8%+QCQ)PIL<(qMI&rH}j-*+#mn<>UEWB2WfVp$w8F!mxFR2gi z1{XC=E~_w4oBw59XgIZ6GEcta$D3^{J#qw@2?=Pa&ymbiU84zWbZqB`r=IA9dMfC@ zX}Yxcuj+lX>Z21F|H5weI~|iA^E`*{o$N1h6FCg6tdo&mu~1>`rBc@X=0%@zKd{ zh--yTOlZPGyx@-X=v=Nn*D|fYbZvQA!>WxZu<;+|okhEJlv5L_PWxf-su$f$0;5** zy(>3ZGee3NEfDa^E70`rEeXq}&(E?1*F`iWq-kg_PhI9o8gg4PPino5=^M=6%zG{x z8<*aRyV!8G(tNd#@6?de57Q`xEbsKyj~Aq*US;yGceemM&fb?w z3*vePN}q#9ij)X!NY;OP+HB5tC6r^^@DI5@CwDvjRc`unmmfQiol01EJ$uCpa|f5q z&>L?^!a|zmy}zBpzrH^QnndDG{vK%>(l}2(+R^Gh0rTfe@fu5M1Zz+X=!J#rCiHcWsFsET1zxKD^#KE;J+}@7tB<)!G`>)?|jLo<-fGhh&B}{rflkd;56{hr4fe z9hoOu2=pH|%t)nqD$`gWUiRwR0$bl5g6CLbj=DzKLj)VHu30<)3t1-E-?wozl_lA> z=i6~G1}iyZS(I4q$m*jZGDDw!d(KLn#l6ch^=u^Y;$II)POB|P*rcF=qIoIC)G=L< z@TX2_6(E0xIMt*)F{%UNqJuDlIn1Yj&x1QcLZZ@nK~XXH%uuR_skGE;TutPZLCVvb z)~J*(^`FP#QYniN9=?oS2Qu-)o-`Y8Wm_gs{+^4{vKv1{o~Auac9wB+Y7H*@@5UUa z)Qd7E!PSDy6BS2W3x!kDWJ^#$l5TYM(YzjiAB~g|{$icwcCaVTSHMb+*p=q;&>h&e!i%k3=>5GrMdZ*wTx&yLlq73=E6$cnzIAKf^X!FzWwPU z9+|SEY9^tS0rqm>R5lcn<6>?lI2)FO?XKjR9JPgPZcTxyEM?sOa~ht1eLv3pk&nO3 z{RLO9mB2^GoM^v>YfK~;3Zn=n^LP@oQ+ z96OU?ZkoBa2>bQPSE(LR9%sAqfEldNxaAJGX!ks8@F!Swwt1kbdKt>h>L z^>_=d>evybyvQLJvT^^g_pJyy-S)uS(Uyg`kZct>#WkMgtkWPH5zS`Fy`Yf&+-IZh z+E*~ueZgCtH7S}zCTc=99HLoZ+=&iteDJ`~2y|{=cY;?il$jUIRYPO~C0cZPh2Kaw zIiO*PW??#l|b0OrvK73D<^#6TBTHAGusjQ3*pNrVNLDDvKqvuLktRh}575{#*1yVRJEMAKrn z?YfApYc&_aAi>a6!)>lSM_t#1M2_Pxuo#~zt4tKi*dtlX1BlEdxw2}NW*A;bFS_Lg zCi7~E6m@=nQV+DWGAf$)T-CfpTrV-=OyO{o{RxCeqXat-I&kK8{d-|g_a7Q7^kHoPNyR7{k z@jq_s9aJOl5!BKH-8;%}0?-tFADYELU9?I{P12N_yPw!5Ik@EK47@E^sxx*9qCsD1 zP)OZ~r0I)!mwzbLh29g-PHGfn!bvMT+V^YR**63;n0H@RCLk-j#IC6r(7m5PyCd-Q*si#gaUEB)>stDyaWQ^$N3`_UV(Q#I*ikW+m!|7(XaC<8 z9Vj(FJm!?%#6n`$;RLB^VAWurgLn|KF+q+WLmj!pgT3(a%6RPhY$O{Rc1OENAB%}D zBD9q!sL6C~;+f!C(-;~xkDlzRdv$sr?ElY$c=z=?B**W>nWop&nJ$3QfBDg@A>zq1 zxft=}4=5^jj?2Kou=mFQ6@Ho?ni!!%g^a;C%*87ub_(WL(LuTk2Gb!=?LfBB5m;4hdo+g_+ z;ZGgWyL$k2O~plKLZ<$?3p%wkuN|g&&ew8Fark&P9)F-MW=-jdg)hdUFY|W-nBA`Q zc}n#rOq{hFmon>r8Q&(0C|*fBG=5s;!y1Y`GT$BQ6X%GL&y&ft=f1} z5(;Zj=L2iPLQwZhTf%bs_gt$%t!C^;G!|^F{xE+*No$E5K=Qzp59UYxf%jPc_lVl`Ws|J0wX`_yK`>_w(WF&C(c!y zPB3S;0L|PaqRFhkyqV)6DDVXwd2N)!5op?JniHK;O1QbY(R9;<*$qzISo>Ksfyq4Z z;xEih?1F4c;7Hjfjdm8TN^weaXnKv;mL*H|AI;n>#-Fm163kLY7Kb*R$bAXfkV%s7 zGj!`j%iu;ittZ@s$2v=`P@B0qnE$fb^79smidvvG1o~vMYhLEcpBnap_8&6gu})G9 z#arjx(o0G^ELeV6YQo%%d_;0~lg3(%c~~5m=H(?Cy~2j6IdFp^3#!7?pso&^y}P%> zhf4D?%!|I(;_JtlL5}w&9_FyCCDgzgXI4_16jr8h%XRg(=Kd z$nIfLE;QzNv9tg+D13YFZ8p~#bQYASx_e-_RHoPzb4m4q$l*L!mi>Iel^-lN7PKlb zl)?56y~l$IOgv;^WCBAzL{0aI=F6;mV<7(T!FJGUTvyLR=I-u+VbU^pM_7_Bzp(ym zcp5XDpkJ1r^0d|E+HA)2)kc0Lb8=))bQ4i@<26(~=06{U@3!14nWBc`?g3%=dhDSQYL?AYo9uQy{=sssB^u1PII!GC#u(Z?V>v47 z%}ZJFteg^LTq&0FR(id_gv2QAPbCt~+<>%8M$(uzb?s-@rkB$XOtZU#hb;Y{k@VskcDECALVdkR!_;HWrS-riwHlDQ)$jKke%uem^OSQ;7yR?)F+=mZp zZFbB(gTkD;_$Viq9?MJ`zgo^QvK%d$M=tIB{{&I+WO(8sXg(-C&Sr&G|pdg zd}WvFFl&)zGKmjBCJqHf!s3?wMFh7-=3(s3$j`8xX`mB!CUJC)IL*N$Sr|7X5k0Z8^aY2zm8uHUbJ%U=(Qx2?h zA$6)Ae0a)_&RTm(R2U1#Urd?$F=XOU$TK}@<_Da}t%OX9w8|=BAwKxq zY3D7}B^Z`FA}oZ%F>;j=ud};kc}EFW{TT}8RYHq!Po1+z3b z`48kAnC5W7^G#*pGE-i>pcGB_a}Z_f%3?F2>CxF=n$r5z>^(Sp-u~~CxGxivX8$bx z-zLHvjREpsCO*~)-)_FwuAX!>W%!d-@zPwb7JiNnw}opEO7BfSHqF5%nC0Ab^-@8` zk5|1yhFxY?$wRUZl*%ATUdu-X&rj@*SKdyNmXeXnxeJ9-4kL&Xy9oSK0IS&ASpQ-tyd~Lz6ea2{^UZfDN}_Wgkzb zLq#9Kr=sZU<{(#~u`JSAoxXj7@cD<9SF5Eakh7OK&{(4aUeM3FbZEj-I0>g#60za- zB2ko^KA>Niw8G6-!Zk)=A=3 z9V896^BkIT+Z2eZ5EwE~6i%4%;?GDvmL)w$b;96sV-0H}wC+S$m|uIW)&gUO^el-HG~VFC{rwvs6-V z#jTmivsMa%FrNBN+kaHKc@j}~45ld&5$1(yukFL$98*-gO>29@1*RO% zR5UgtdE)!1C+fYxHl*)cT_C8oaiZM*c{=vtDEiy9J2_Jpnv##7Z?n8G9t9&w1MS|Q zY4dfc#8NO8jkugL)kz^?%eds%2#Hx40p9p6i@S7}b)Ynpl5BW$mA_3y<3W)tdNd>H znMD13UImPqc%Q7!-^6`!NjWvpUZ*^ zaJjw@ja^PH(cWV3ETiIyK4ztfYDR(+b2*gEN;^1tBV0&>I0(UgS48nf;X9^nI?Fn+ z*+i8i8g>Y3g3)~vM4KEtD3(QxMQ?OkhxXqX~tj{}t5|oO!+ z<9jvj;kRh|gK6N2X-VUD!wqn|vm6q$bRJ8`PLwA&m1atVCgb0T#%r8tSlZtElVypC ziEh)z+$}H5(70u-*%?a^IX*$2;80DkM}^=tQjH^;vN>??7U_(u@)8rARK)8%-1@AB z-Tqd%U{Z}^N@KD-!6Cm!*SG{n6xc9X|7MXBjq(%E8NTqop0?rCsReG|?Wob|?Xb8N(JT}G95Yu#*oTj@?SroagB47GNM$%LJ(1>W%LyPd(rNd1e{}}rcBiO?L`;H=EA&sM{ z5FS^Z0#lAC;NL8#wz)*OdNTLW%lT-8G?}qzaNOI26r6IHAc+0gFmxdMYIfM5$|7`i zh4479Wr!#WMsUJU3QkNGjK$xiAAZ__g;?E>CKFdF%+A<+vLv~Xi_B)4h9N%7$76=oA* + + + + + + diff --git a/assets/uco/icons/changePassoword.svg b/assets/uco/icons/changePassoword.svg new file mode 100644 index 0000000..3945d28 --- /dev/null +++ b/assets/uco/icons/changePassoword.svg @@ -0,0 +1,238 @@ + + + + + + + diff --git a/assets/uco/icons/drop_down_ic.png b/assets/uco/icons/drop_down_ic.png new file mode 100644 index 0000000000000000000000000000000000000000..0cda291dc72f1ff0f409569a81f844bdd5611c6e GIT binary patch literal 814 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 E%Ux0{L#r78bGRb06B(lx~@=YqJPBy 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 + + + + + + diff --git a/assets/uco/icons/ic_activation.svg b/assets/uco/icons/ic_activation.svg new file mode 100644 index 0000000..06cd521 --- /dev/null +++ b/assets/uco/icons/ic_activation.svg @@ -0,0 +1,317 @@ + + + + + + + diff --git a/assets/uco/icons/ic_activity.svg b/assets/uco/icons/ic_activity.svg new file mode 100644 index 0000000..b006868 --- /dev/null +++ b/assets/uco/icons/ic_activity.svg @@ -0,0 +1,164 @@ + + + + + + + diff --git a/assets/uco/icons/ic_add.svg b/assets/uco/icons/ic_add.svg new file mode 100644 index 0000000..012f6a3 --- /dev/null +++ b/assets/uco/icons/ic_add.svg @@ -0,0 +1,92 @@ + + + + + + + diff --git a/assets/uco/icons/ic_add_new_Account.png b/assets/uco/icons/ic_add_new_Account.png new file mode 100644 index 0000000000000000000000000000000000000000..7f4899ce7c09e9ea60d33ad4f907dac24f2af9cd GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8oCO|{#S9EO-XP4l)OOlRpde#$ zkh>GZx^prwfgF}}M_)$E)e-c@Na@?LSjv*C{Z)b0OcQ8Pvwf^6~BisT96B4&Q zkhEd?I7=+<(3zx(9E*LO=16btICwyD`E&1m+je^YUb@rw@@%nYe|f)$3~>+4Iz*bi zW&IL3!xGrnJv8+A!#e%eRj79q8lU+1wLtxjEa^zT=b+lY}Vn*S;v=`wEJ(6{+SSX zg71=1TGY+oU+(4|zIXVBP~M}@G7rA}n{qGJsDkI-5#3o$@itdbEI_k0{(+Fojf3s# q$-fm2{WE?$<7Pv;Mf+-nB36C}nI#NuGl0Ruz~JfX=d#Wzp$P!%n4c~H literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_arrow_down.svg b/assets/uco/icons/ic_arrow_down.svg new file mode 100644 index 0000000..2d06387 --- /dev/null +++ b/assets/uco/icons/ic_arrow_down.svg @@ -0,0 +1,102 @@ + + + + + + + diff --git a/assets/uco/icons/ic_arrow_down_icon.png b/assets/uco/icons/ic_arrow_down_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..27e37196536d5a9b546db547ef62f50570f463bf GIT binary patch literal 792 zcmV+z1LypSP)2x|xdIdzsX+<---R>8|FuvF8b$hW`{H8Od z*Xw=d(_O7rBOd3UX9)=KX%O6Agazo#2*!C6+`NF#B#a( z%S*`POGhklE+Ps6;G5x9sZ{#Fr@5rifM@C>{YO~f6G;RPhr@ic*<2aX#D2eT?{>Qx zU%HYC{qcBwPbUTskeB+9UXEwA-EJGc@2?Fpv)yhxTxrIKBj)Y*`^(8>@<1noX8;fL zQA~#b9~jFD_oi3?87P2)VxDQ5(^jkH(g}b79;TQs3IIdZNX(3^c}5!1M)C%ITbA|6 zgSDgSG67(!8VYBGFV{kr%`-AXM^pf47wwAz7>7&%m=r@$K_=o9ArcDE%TGP}zf{e> zaybc&dqLwOtKel{QAT0}Kw~r-%~f?{XCee&Bp&RQBnur+o6V+889;rN0Q!v+09q1& zMTQCyw^FIh(u$xS>XSr(-+|BQ_gEX+5+G>sR+8nG%jGGhfCYY# + + + + + + diff --git a/assets/uco/icons/ic_back_white.svg b/assets/uco/icons/ic_back_white.svg new file mode 100644 index 0000000..01780e5 --- /dev/null +++ b/assets/uco/icons/ic_back_white.svg @@ -0,0 +1,78 @@ + + + + + + + diff --git a/assets/uco/icons/ic_bank_transfer.svg b/assets/uco/icons/ic_bank_transfer.svg new file mode 100644 index 0000000..cbf40e0 --- /dev/null +++ b/assets/uco/icons/ic_bank_transfer.svg @@ -0,0 +1,218 @@ + + + + + + + diff --git a/assets/uco/icons/ic_bill.svg b/assets/uco/icons/ic_bill.svg new file mode 100644 index 0000000..da95543 --- /dev/null +++ b/assets/uco/icons/ic_bill.svg @@ -0,0 +1,160 @@ + + + + + + + diff --git a/assets/uco/icons/ic_call.svg b/assets/uco/icons/ic_call.svg new file mode 100644 index 0000000..64ca357 --- /dev/null +++ b/assets/uco/icons/ic_call.svg @@ -0,0 +1,234 @@ + + + + + + + diff --git a/assets/uco/icons/ic_camera.svg b/assets/uco/icons/ic_camera.svg new file mode 100644 index 0000000..824e6ec --- /dev/null +++ b/assets/uco/icons/ic_camera.svg @@ -0,0 +1,451 @@ + + + + + + + diff --git a/assets/uco/icons/ic_camera_profile.svg b/assets/uco/icons/ic_camera_profile.svg new file mode 100644 index 0000000..fa91a70 --- /dev/null +++ b/assets/uco/icons/ic_camera_profile.svg @@ -0,0 +1,242 @@ + + + + + + + diff --git a/assets/uco/icons/ic_chat.svg b/assets/uco/icons/ic_chat.svg new file mode 100644 index 0000000..91a660b --- /dev/null +++ b/assets/uco/icons/ic_chat.svg @@ -0,0 +1,225 @@ + + + + + + + diff --git a/assets/uco/icons/ic_check_status.svg b/assets/uco/icons/ic_check_status.svg new file mode 100644 index 0000000..cd3c3ea --- /dev/null +++ b/assets/uco/icons/ic_check_status.svg @@ -0,0 +1,181 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cheque_deposit.svg b/assets/uco/icons/ic_cheque_deposit.svg new file mode 100644 index 0000000..94b8b01 --- /dev/null +++ b/assets/uco/icons/ic_cheque_deposit.svg @@ -0,0 +1,185 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cheque_management.svg b/assets/uco/icons/ic_cheque_management.svg new file mode 100644 index 0000000..56dc9c8 --- /dev/null +++ b/assets/uco/icons/ic_cheque_management.svg @@ -0,0 +1,117 @@ + + + + + + + diff --git a/assets/uco/icons/ic_chnage_pin.svg b/assets/uco/icons/ic_chnage_pin.svg new file mode 100644 index 0000000..55585ab --- /dev/null +++ b/assets/uco/icons/ic_chnage_pin.svg @@ -0,0 +1,269 @@ + + + + + + + diff --git a/assets/uco/icons/ic_client.png b/assets/uco/icons/ic_client.png new file mode 100644 index 0000000000000000000000000000000000000000..6ae5613df2cdf90c2a5c8410ea69b735145ebe69 GIT binary patch literal 4324 zcmV@~0drDELIAGL9O(c600d`2O+f$vv5yPkwpZ=fGlEbQA7uNQsE80;C?JFYS)jj<%nS1-FPXPY^4`mv|2a1^bLY-|GxtCDyZ8IP zJ72<7BVpvokuAVgr%#{0opeQ5SXd{r<5lxR70>r$czF1iY~P8DjLgr?&HbNhB!sC( z!1(dwQ%{{b^(Z7=!C|BdE$o4~;;O2uM;0wwbX-}C2xTE=&6*Y7zJ2={?7jq9$!x<_ z=pl(`9~2Q0(XUURK5MsZ*;1w~gq1xkEHg9nIktBz*Dpc^>6B`oh^;4oBa$X<;lhQb z$|6`Mt{`iSs!Nv0_fL`U%ee7R*q&6)5Y^Syoq4w5?2aNO>Q42ix6NUjr7VIaJuEvr z`#f&?Q+6+^tvD=92Hxii3JRW5A%fAPN2kQZ#4KR9x8c-Hg@uLhD+^%B7(?&5m7df| zmsP>>qmVUQg%B1mUi>*P>K&w=hEop=88XBYY34Iw)22;}ft>N&WNmL{cg4<~J6~b< zv9|SGtu$AuA`;how6{4U$V%YrNkX^vA z@nUpz^p3o|ykp8sctsdQ#X;2V+}M2_UaTxu51K1@iACaUCB1>3mW!TtP(ozP}xr}E!nH?QbHtI!cYHCc&mMt%*tsdm?dI+qYq_Mwx|Ni}{>(;HS zGONd}$wJ@0eMeB~pLFFbNpqO-JOojDwr<_pEG-yTqNJpxdi(b6rI%iM=?bhOqLW>v zG)ogbuR}sY!lrH8wtZz*kLjd=-W82vd?&k6y6lySiHUP^a&k^68y-O{_|kUlzNgEM zhQtS?t=}P)bZoThcP})rqY2BbiSd;0cFD{(56weZIU7T8`5S{ZdqB`n&r!v zA2nWAhp?=ytRWEf0+n5+oW-Dxrb8u!e#UkNQ~nS2C-jq!u#Ak1yCCXy_B$!tdf`t* zz(YsUxZb^cpI}nA!EvIthoKZtp};)l+DBHdny>RQP$2DI#}P_TJBgllcYc2Ud^tWt z7)tRC%mj-dOs^Cl=lB!E;{vuHGmEj*)osHWwEvl<1?-L|T}`T;F^X>y9){t${ydDS zWCTj_8uG8vU0*?=*%cKPvm0X}iH-UphIROu$?hLWEp?~Xpbm_PNJ&W<$iZLK*)dDp z`p=e@mj3nKci*j0HkuSWcI>FaceXw*F78|o`>C_Ka)*;APyQ={LG3Z^gacccncTK} z_ilU4@)N`=(yLdm&yaFAap+K~q(g-XdxQ0bDO99v_#Jeb1B`3S^m$@D4(HDWy1WyJ z!;h7XfB@Y5Th%NNbRb#G{`zHEvSiC1w*myr%#G?)qKL#sS*~rPQ4nUk_=5~KVL=9) zupom?SdgK~zujV18a8UwsKl6KCUJ;P?rN`=M-DM;K%cr(uWd>J(Sa%Zx!YJkd8G?eB=q zKeMa<=xsnkLPEB(VU0+Xg{RVsboEt3-WMo{Im!zNX^6;7c4bkDcv>0e!tY0KdEHaJ zMZh@NM|%mns=$P-L(DmR_^|2oSwdKOdATe)y;7HTj0SqRxVYHs&t@U$4(eF1wDFJ! zx){Ah#mdpM0%3Mr_jfd`r6k?LVkY!PR-+5 z?Z|_)vC2CHYR}R`I?p9$g?uJVCL8pI0fy`)$^t-;#Jtek8N14NR?2hal1#t7@+Wv! z`LNIQ0~4P`VsvzL0zcMWmnC0hS`tKr9=3_PMQ3unc^4oS#s0U~gK9)ko=#&Fs~U?- zAff^(wHc|j$E={wgfTwE(Xi(j@;qwL`oIixFLMw5mz{CcEsC^9^`j_@Sp7^(K@Fcp zA|@Uo-5W9G4I&Z0P4!y=37-kW!Y+2crt)W<4)qV;eI^WXD9hr?RntIXSa}^qra8c8 z!Z6-S1OA}PibZUVQ5FCjVw!TE>K@|veo`R}p9#~xZrP~Il1a#g$^uZ2Skx1A$Gg1= z_tTtUiQ-H{N(_%$JqNLshJNM~Y1;Lo@an$=U8_PImJoLI=u!C&S3lKGM(>%Xd;t30 zt!xJBvdR&)IV!|q31MQ5r&lf3Wl7wLDd9 zV>oVwsGJUI1C$34QHXLZAI2M%@#mBc-z^=?U5~4p(0)!)4Ct{d=y~&nOq`wHs1SuuJxo4kr-3DO+$>eUovsUImLw)7zE1g} zt_skr25|0G%E_{?I%H{R3t7|Ien79iLxm{3>S5xphk)typof%;#+6V7G=79uzij2> z>apbCKx4~7(J1YlSS`e17sWYaSU>sJx>^gz>VUjpok_1z&u=j5-WzJue2;sWxHoXu zOSEhWBj-dG4SbOFPj)kC=%?8l8&g8{$ih(}M@Vd?JJv&@7|hcYa0&J-QO>FjWyWL2 zoKNrc%j#W!!J{4~O92>*W<$zk!?j|bDxi^{DlIMjR*U<$lrd*DVoW9@DayUbIzmbb z^*nm;;K9Y3yL<(toX<4>9)9;8j^nhl^0M6$85vo|eNCD_e}1L%0T~$?9eF|e%Boz| z#Gs9;NFTW)Ej+q8^sOu!bE^J2j^&@j+>I+_xpBcKUgLE%_SN)+Ybi5Di^%C%SMPu{ z^dZh~qrv83O#XlycM9Udv6#MQ(5P=xMwZO=)K1Bw(@b8X9qi9hUV`!SY8p)ZWf$tA zxi=ZmStT9d1^<fE#l>y~JJv(uX^CT$XB?(`#wLTfsJMrfBvV_dTZHj2LwJx5x~%UIBXj-n zA)W(_r;A#&XmKa^)nChsmrs`1KBPQ^Cbs8kDWKub+Z0Bl+@dcl$};1{ZskX4_DfN; zYp46%*Y&EIhp{jvY~sX;Vu01#1FLDMK#BJ&B1FFq{~~6ke)$ZxsbESNqDQ`?YNyLO zB+JiK005ou3pVT7!U=W3DIs%zZ1x(sF$-{ zuP-Oo5ESf(DJNr`TcL3&yBFQ)zTDj0)voGdH-l7IRaG@pA5&6`L_UJu=T%(`PJNKI zD*48`T*0)5F_0UVIqxO~OmtFNHekrAvn-ou$fTV7yGKz2TDg;Gz+TMS=F1G(Rb8a> zN%umYlh3cDq@=U<|7kkA`&*>*w7N_`GBoXB+;oy&`{zOSX$v!JAttNx^75N0Tg}Yv zJzvd4ddO06FqqU48|G5#c3PoD1MX$UT6^pww76IiL|ONEy3Vtj)g{5zoNSpiK|J@6 zs60oVx?C1AE5MJpFdRFXpQJ${Yc7rUmbg*M%F1SoSWp&$x9%QDS z(Cqx~X~S_#V;wZ27^F8-hbYJHCixg~9%AZ%tGZN;No_p@=IGB;emlP->cMe$e@nZs z^*pO-L;=$tCdSZ)>}#>HvFGp*>FVs*kbziumhFCJ4dfFehjM&Xw{G2fY}&MGOMQj8 z*E-LHGW~UScJ__jXR`dKA>{@rcc@F3E_MD(gQG57I~P*lH%Oab^yfwTAaNe&C4QT> zi&O4_>MBc&b-9AirWk%GQv2sG4#e@6S*8ooaJ3Ju#kVm1|0J$}ty0!ATC%3mtS)Ux z_(C-T>{wGl2Ai-TgFmg)O$My{tr4w55vR$@KiJREvCQb_6YqUeQj+|aUP&K`QQNGd zkRS}a09o?y<^3g5PRR^#pC;iLPaFrto-||;u#-` zPth1_L=4)>7LYUi5)<(o9O!bW>J+aB2`6dAg@C#~!Y3!+x5Q!+$Q+a#W zk}g*M!C_edYg|anxb`--S|LmRsoq*#R{t@pC?p7@Ate6A^D4lgIZhX9$t~E^`XGZ% zSdhURkr;)otkyrqKpL;NmY=CKGBRFY#us2rb~?rk=2SNZVOi$ZU>#bdxwc&Em;dQW z`&1Sc6?q(e)D=7?OxAbcg}zLe70Y0*x9>@yl?9ZsB-k>IoU9{649tI{?%HJm?yM(_ ziHRA(4D2y~DbC!Z1frfPlMJJ4%2RkunASiIHIf9S9BkDJT0`#bY z5Axfu(90!umQOv+9eqo3J2*O<0h@ zCM?Kc6BcB!2@5jVgasLF!h#HSOjFnkFU!ctu=GFT+3*h7AbS{HNk+mXFy+h2Mj*lI z;}0QBdXs}j5s`sxkq>p82_h1*!6JhVh{qqok&_Z7O@eRP<5u88xG90B-~AuU476^p Sn%~|40000 + + + + + + diff --git a/assets/uco/icons/ic_clock_circle.svg b/assets/uco/icons/ic_clock_circle.svg new file mode 100644 index 0000000..c2d051b --- /dev/null +++ b/assets/uco/icons/ic_clock_circle.svg @@ -0,0 +1,151 @@ + + + + + + + diff --git a/assets/uco/icons/ic_congratulation.svg b/assets/uco/icons/ic_congratulation.svg new file mode 100644 index 0000000..5d08598 --- /dev/null +++ b/assets/uco/icons/ic_congratulation.svg @@ -0,0 +1,456 @@ + + + + + + + diff --git a/assets/uco/icons/ic_congratulations!.svg b/assets/uco/icons/ic_congratulations!.svg new file mode 100644 index 0000000..b306cea --- /dev/null +++ b/assets/uco/icons/ic_congratulations!.svg @@ -0,0 +1,343 @@ + + + + + + + diff --git a/assets/uco/icons/ic_contact_us.png b/assets/uco/icons/ic_contact_us.png new file mode 100644 index 0000000000000000000000000000000000000000..cdacc44877c6c1d456106440a904563cd251b4db GIT binary patch literal 5688 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 eF^GGe7W_YuY>vkUMYk*f0000 + + + + + + diff --git a/assets/uco/icons/ic_credit.svg b/assets/uco/icons/ic_credit.svg new file mode 100644 index 0000000..fe98f01 --- /dev/null +++ b/assets/uco/icons/ic_credit.svg @@ -0,0 +1,117 @@ + + + + + + + diff --git a/assets/uco/icons/ic_credit_card_bills.svg b/assets/uco/icons/ic_credit_card_bills.svg new file mode 100644 index 0000000..eea7150 --- /dev/null +++ b/assets/uco/icons/ic_credit_card_bills.svg @@ -0,0 +1,144 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross.svg b/assets/uco/icons/ic_cross.svg new file mode 100644 index 0000000..67cdbe8 --- /dev/null +++ b/assets/uco/icons/ic_cross.svg @@ -0,0 +1,165 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross_option.svg b/assets/uco/icons/ic_cross_option.svg new file mode 100644 index 0000000..bc8ef87 --- /dev/null +++ b/assets/uco/icons/ic_cross_option.svg @@ -0,0 +1,140 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross_white.svg b/assets/uco/icons/ic_cross_white.svg new file mode 100644 index 0000000..af9e31d --- /dev/null +++ b/assets/uco/icons/ic_cross_white.svg @@ -0,0 +1,113 @@ + + + + + + + diff --git a/assets/uco/icons/ic_current_account_arrow.svg b/assets/uco/icons/ic_current_account_arrow.svg new file mode 100644 index 0000000..b690338 --- /dev/null +++ b/assets/uco/icons/ic_current_account_arrow.svg @@ -0,0 +1,160 @@ + + + + + + + diff --git a/assets/uco/icons/ic_customer_service.svg b/assets/uco/icons/ic_customer_service.svg new file mode 100644 index 0000000..84bb24b --- /dev/null +++ b/assets/uco/icons/ic_customer_service.svg @@ -0,0 +1,159 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cyber_security.svg b/assets/uco/icons/ic_cyber_security.svg new file mode 100644 index 0000000..6177c76 --- /dev/null +++ b/assets/uco/icons/ic_cyber_security.svg @@ -0,0 +1,437 @@ + + + + + + + diff --git a/assets/uco/icons/ic_daily_transaction.svg b/assets/uco/icons/ic_daily_transaction.svg new file mode 100644 index 0000000..3682ec3 --- /dev/null +++ b/assets/uco/icons/ic_daily_transaction.svg @@ -0,0 +1,324 @@ + + + + + + + diff --git a/assets/uco/icons/ic_debit.svg b/assets/uco/icons/ic_debit.svg new file mode 100644 index 0000000..39d481b --- /dev/null +++ b/assets/uco/icons/ic_debit.svg @@ -0,0 +1,110 @@ + + + + + + + diff --git a/assets/uco/icons/ic_debit_card.svg b/assets/uco/icons/ic_debit_card.svg new file mode 100644 index 0000000..4ba4a47 --- /dev/null +++ b/assets/uco/icons/ic_debit_card.svg @@ -0,0 +1,176 @@ + + + + + + + diff --git a/assets/uco/icons/ic_desposit_account_arrow.svg b/assets/uco/icons/ic_desposit_account_arrow.svg new file mode 100644 index 0000000..e3f7937 --- /dev/null +++ b/assets/uco/icons/ic_desposit_account_arrow.svg @@ -0,0 +1,144 @@ + + + + + + + diff --git a/assets/uco/icons/ic_device_management.svg b/assets/uco/icons/ic_device_management.svg new file mode 100644 index 0000000..3ed645e --- /dev/null +++ b/assets/uco/icons/ic_device_management.svg @@ -0,0 +1,319 @@ + + + + + + + diff --git a/assets/uco/icons/ic_dollar_symbol.svg b/assets/uco/icons/ic_dollar_symbol.svg new file mode 100644 index 0000000..6e89e61 --- /dev/null +++ b/assets/uco/icons/ic_dollar_symbol.svg @@ -0,0 +1,120 @@ + + + + + + + diff --git a/assets/uco/icons/ic_download.svg b/assets/uco/icons/ic_download.svg new file mode 100644 index 0000000..42a019d --- /dev/null +++ b/assets/uco/icons/ic_download.svg @@ -0,0 +1,136 @@ + + + + + + + diff --git a/assets/uco/icons/ic_electricity.png b/assets/uco/icons/ic_electricity.png new file mode 100644 index 0000000000000000000000000000000000000000..7e13f546fce16f709405b02a1b6ce7e460dbe60c GIT binary patch literal 2477 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 literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_email.svg b/assets/uco/icons/ic_email.svg new file mode 100644 index 0000000..82e310e --- /dev/null +++ b/assets/uco/icons/ic_email.svg @@ -0,0 +1,246 @@ + + + + + + + diff --git a/assets/uco/icons/ic_filter_statement.svg b/assets/uco/icons/ic_filter_statement.svg new file mode 100644 index 0000000..1f82d5a --- /dev/null +++ b/assets/uco/icons/ic_filter_statement.svg @@ -0,0 +1,76 @@ + + + + + + + diff --git a/assets/uco/icons/ic_finger_print.svg b/assets/uco/icons/ic_finger_print.svg new file mode 100644 index 0000000..c248d87 --- /dev/null +++ b/assets/uco/icons/ic_finger_print.svg @@ -0,0 +1,361 @@ + + + + + + + diff --git a/assets/uco/icons/ic_fingerprint.svg b/assets/uco/icons/ic_fingerprint.svg new file mode 100644 index 0000000..ec175fc --- /dev/null +++ b/assets/uco/icons/ic_fingerprint.svg @@ -0,0 +1,645 @@ + + + + + + + diff --git a/assets/uco/icons/ic_gas.png b/assets/uco/icons/ic_gas.png new file mode 100644 index 0000000000000000000000000000000000000000..baa1cbdfdcfa1b3a418fdc74becb8ee5228fdb40 GIT binary patch literal 1928 zcmV;32Y2|1P)vAZ%^=Y;h4 z*nyi^(F@tOI>qS#UAxvx4-%03*b#pXNNl39pIwPKm-cXI|Ntd+XO zY&MF@+*EydH2FWKUx`=K8@R4r3!6m_o}m8iQ5ORz>cYL@M*s4$&A--IPn(7}8%9a7;g?{9T}1Ra z_}rZo0AAFqv$~kCkkXP~Ec7&@ywzM)GrytJp`%+YA(k5`C}DY{PcDlLHmmDY)l8;< z$jK9H!|*QM#g#d>(siCcvk#A7djev&7P^jt683UCnB%fDqOQPXEt!OC0}wk4^}t>j z$&tldoAfh*6!WDNlrWtALssh80?HCVYLZh~6KSr^6EP;|z=gW0#;0sZK(5D5-ma=w z{6QJuL`6xDkd}UK)zTTsIvfhmA+R_GA3i75IL6YOH=>hHM?CjY=7i}gWD|=iL$ni` z0zW&zD=X>-+qYL&JnA(0w8-%|RZ~inz-O_62ou*)hCqyKGYr^cBsQY3kMDs>5`6M= zQwCKn*>JkmZx%AF-Wh;mK5eS|V(Bwno}OnZT9j5|axK z8!>kk1u`O$)5V4r^*w=uDCJl|L?^VhCG{x@n^YZQAGSen@(CQ_7lCP^P5Y~s)iNoQ zIU^S42j%UO_Kr)nIZo*FX2+UaBE%BddH+xl!l%@%g@Ue9+P4$=0jr@1VlIR8ueSeP z$6l@=TDw2)YJ`_;%&Y*RWq#wK$Ub`68HMIiP{J6z93re$?lY7I_3sp41sC|HJr(!v zv#V%wI(*`FSh=3K(HxxYtD|~Qte}zy!0lro{miBoH+5A&bp^K0FMMWh-`zmg{zjYr=Wy+%=`nGZ~-Rh7po||H&s8} zD?E$uemNZfG=6_^?b)re=TzZ*xVv|uYd03)tPt`%FErfT;Iq~rQ5vL;)|7JIg*fVn zGwomsTUJaj8dNVBdl1)LOz^xo8VkIRe$) z&vkOYZuXoPx*5-(bCEtZogi#)0%3DAr@}D2g4Q?5TDGk*a?M?z4Dw&Ew6DlVL?&#bx8Nx;NAj zO;?pmhCrW?Ph?EkPE=kp7&AnSUE{X{<@r!#PPl8(yus7-N~n728rv6F177=3e?>AL z?a7RIFJ5jWUTz9yh(Lr5_75xS*vX+G*g-EPh&RD5DBq8lF(mU&&2|vc-$XhZoxl^4 zS;+rH_)G|Vv=;R^R`Dh=DUQ$usE*>d2NTpGfciyav%29sYLlBaDE + + + + + + diff --git a/assets/uco/icons/ic_government.png b/assets/uco/icons/ic_government.png new file mode 100644 index 0000000000000000000000000000000000000000..716a165ce4a092e794da5b2def2f03ba1c82e67a GIT binary patch literal 5091 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 FV1g_pw;})l literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_holding_money.svg b/assets/uco/icons/ic_holding_money.svg new file mode 100644 index 0000000..e49bd5f --- /dev/null +++ b/assets/uco/icons/ic_holding_money.svg @@ -0,0 +1,360 @@ + + + + + + + diff --git a/assets/uco/icons/ic_home_icon.svg b/assets/uco/icons/ic_home_icon.svg new file mode 100644 index 0000000..c9805ee --- /dev/null +++ b/assets/uco/icons/ic_home_icon.svg @@ -0,0 +1,143 @@ + + + + + + + diff --git a/assets/uco/icons/ic_internet.png b/assets/uco/icons/ic_internet.png new file mode 100644 index 0000000000000000000000000000000000000000..a703cad02fb3e79d0a16223e1f46062fc927787c GIT binary patch literal 2083 zcmV+;2;BFHP)Fyq-CQ0gQ-ZHG&bngeROmbO-p0DiKFGK zMI%EL#8xVyiEd1Eo7kkTb&|&2&C5hwr-aY%>m)OdJoeyYY zkT{a#O)AhEiS`N9%CFq^P$L)~qpR`jL!R;}ZXV*^lc4fGlkC-@6PUowGl zky^0vfEwwKlISzG8Vm)n7<$mwYM0W3OJ9$crR!zcP@#*Zra-5Z#+RgSzIK1w~mDW zsiUQ1WgnttIVnD;Kv^rIlZz#+4?%g>{|(sdGAPyBRi!m=@tA9@ z*6s#3QvG$HD_NShik)@DPq z#A~hwDZiWZxJZk&4FWf@hfO>3Z<-Huq&5k~Tr=T06`9;%CcuN(ln(BOQttQX(b`7X zb2GI2RlBY0i3R5p*fa&3Z?xKb_AhWL8QT;q*lWh@>TmPD?&EoR_ibHH7suP-VRj;HcM-hY-yxs0d9Hs?=8>`!{G{vBR^2|06 z9(Rr549Iw_qcFb+w#qgPnyNEWH27|(CAEO|%a-EK)7!p|Wj^Vj2k zT#M&@9I4nSJk`JKG50y+9dfRtc>;ufmD{@ZW#$s!^dWL|6TM5|mTnWSUz;!glBJiI z3Va)uXf;BnwF9Y?B^<*RnVES?+k|KU84wqO}j=t$htOTsiXK zx4k)Y>24D7exwQ@td53%57U}Vh*$KJkni4fSY_QGlsUmi^vh0%Wb{y+}Z~MFE)H2@M6Pz zMqtw@5v5+9i?5(=Z8~sk_qWWip9RhWQv&lwgy@qv<|mOvTT~!`miu*DdU%$y!k%LM zvS}M3-+xGnI8-3e%-16W+C3Xj#v~G|t!tARNJGuaEOlsjgwc`7Ol3D-SIC__e~~w8 znsn12X8yOJ3F|U59!ZVKiq2CPa?x@^k@sIKo^-uvO+QNdye(P((xF||E8DhND5=lD z@Xu#IA6_}+#KM*S=_BFOQlf{lG$$~QB64e1pvLefaqN){eR;{UAswrI$)}lSwrdam z-?L|aoWObPzg~%bfacV&q7<#YxEgiaHBes@D$IT#t>jUgxLSTt_dJsI4Jhv)7gl~h zLJ4&u_M5lzJO4ngR57bjw90mwIV#BtBsV)G{>4?=aZEpBxn{a^7R?<*hjOzjqDRP? zOW{o3a< zjHp)r2>K5#i+iWY<`e_V?oYmf|0_<~+74!DIYHzi%Kl?C_Ev}jC1#$pIcX}6zhI*` z(C@lc;x`0Sbj3$A#1I9?IG#8+B@m~YtJY*`4mw~n8iTT@qAV4%S7dpHX*g4^%e|GQ zsZuJ~;Z+em1dg!_X%Dxfps#o78up6oU243btjDHKQJWB<1Ysykr!EC;d z=K3R6ThI4$@l00DlmASbrrV8FsBn#v8Pc4?n|w^2DQn`Vp32$!{U3*^ddoC(nF9a- N002ovPDHLkV1laj=biun literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_internet.svg b/assets/uco/icons/ic_internet.svg new file mode 100644 index 0000000..9752e43 --- /dev/null +++ b/assets/uco/icons/ic_internet.svg @@ -0,0 +1,471 @@ + + + + + + + diff --git a/assets/uco/icons/ic_isb.png b/assets/uco/icons/ic_isb.png new file mode 100644 index 0000000000000000000000000000000000000000..d3dbd6f47cc214ae990fb2b55009598b9c45badf GIT binary patch literal 7133 zcmV<38zSV1P)gv6lZn~k_6%mXLDknj4iyKDceiBV)vUrY~921>6$E*`4i)K6VB$+r# zX55t-MTr;{2#bIqJF;~{0}b@vUA@)*Z}YwP7fYkYB``myD5~mT-n;MK?|%2Y4+T72 z*ImK4c{ojnEB`2?zEMy5?DD0!4*zzLb2aGJFcjSnMbY@u#jo$Vr*q0Dm48n2u~Jc# zi^V@q`<=z1$Unj?Heb#tgN#1J)LdkS`o+pfV}0;Fox(lE>x>Nhq*0xLgPzB~9Hf%{ zu&pc{XY_QH!rx+gisB$Yl7Q_9UvS^|UM}zD*cprr_j^~lIHSiIGP&m|77db3k9?q? zh_x3UVr7Tr`S_qS`Sr+fLK@I@9h~Xo%y^2NtBO!4iu}P%GneF+44Rsg?mbG5=O}&$q)>bj)SQMyl}&rJwB09 z+~Y3?gM;nJa^RN5iCB4w1l~=9^4%($04Lv#TxY8c8(ZRuEz`8Thn3>*18_|fD!oSF zh)VAe=P3N_^zMX_&ma)3h9R?+_hP&u&zECnV469Y3_qFmPQ&q!c?t)iX&UnVhlmGU zRn-R#1#eJP$t_%xv2ev0WcRO=#OxRS3rwb@qWHh zgH@aYYa#HahT4$Jq?!6pPiFcD!$(6nRDxVj2l7KlAg5#rM#^NXy3mj!$S5_oO!+r45sDXxl4LMw;Pr@CtHtfAJf`gc&7JHNq5Fm8(IB*Q(taUp6O#`BjDPLGfL14cRd5TKVM zmPD(kbHz#7x4t00rLU+3I&N}~VFb#m;S99G>e)wQ8T1Cvux@(514vth3=Pab;<{|d zZn(p}&??69c808X#B~nCQK4beyB5Nq^TA&`okqJ^jdH!0-yuPm@uF@0v6%!rp|m_Y=lI3oQxCd_@Sd8G!mq=BO} zn2`#+m>!bv+>HKrUqi(?*YFu6cbZYCxBD*SZwaN}GIZGHiE z=O%`S21oV7;6MVU(Zoe0LnlwWP6+|3e%G z@m7JzJCSMg_%V*bP0zu}^l>GLF1&}Ysuo!?+-PbU!MC55p%$NVB{acs6)&*7RPGT;VLnk+iJ-D+XqVwe z@FJ)W@!uIqBLALH@xDfJHD08d$eRgt9Nms&Qk3=z@l)aII|AjHT@;B6l9CAHs3NQQ zp+;&DJZm1@-hQOk{2p#@7$yhr1fx)5bqF)82KKI}up|JLo|GGr7^0HA<$0c+?1j_1 zM!+fbVj3h^4wH{jN%DHuJ_mHXix|U33s=Z=FUuuSBp#C@L@4tav>@NJl3iyqNwl}_ z!a!e-tg;p56L^Y9nGRhy5R9RsVl2{!)+4d$SttYhp;?~CI9vhqm@riE7|An9#iNri zfnHjJ5U(5F@d76;vIY%SK3%S#(Q^n^U#qYqfi@vYnrfMH0=c$LFb4P0ki1{XL_l33IN>bM&k>jfk<0cTKyJem7~Z-V<@D6D>UtKb zehJ!t&o27=eW}TaS0#%y{N*T{axF}*Q2$$hhGl3dKKn96Dkrgkt)zhzDI?13q~5{L zMhSxFUxm!lHt3t)Kq?$T(ZmJN%cl}R8Diutg9n$RtoRn_<^XFXKV3VIFw^o#^GZOP z$$&m)0`Et>VK|vP7Kz*gZPp!pZj8?w4I~b+MJ$$?()DW)+`SRQ8=r(fI*uf)8Ywj>5;Dxzb;#FEMvhSwq1O#D?sMJS;0zz3 zr;1?(5G);wTw))R>z;w%N+LJmGQ{g<&>+&CSyp%`q6@=i29RxCjZDj1gpVBjQ|6;$ z`XzMGB61~tv`YLT;iG@p*D}6D3KfEKpak*hmm*qMkM_5ofwuY&NN!jR-}EaGn|3}l zUnz|k=77mUY0#2sH>3Y>8~iNzdRF{5>K5FC6wk5v*`V5%+xr$7tHpa~=rO}c?puoh ziJc&GW^oM+HGuxrzd$J41v6NRl5?(xPEI7S!%_sarJ&G={d;L(mJuMsRZ8j+zvOlp zRp$_D0tFj0 zZ+qs=C_eWt$)H_QLu+6+Mq1v6MMH*Ye`72 zxs3=lr*tYJO*g?`CAg4ZUax(8-tuvcQotCQWmKuJ%3@D^NB&@$gBaNU8vMInhmVzT zmMd(lA-EOw2u;0)062)un#W19Y-tFE#?5I#8h}|W%-Tke$XZ5VpjwW|`L}QZK0{+fgel~dgevj>V3bpiQ@RljvyMgQ z&m?vtv-WAkn5k@CLskh&!WIhCK-m!*hoMJSo2_X=aN+xWrT9QjBBsX(U~rXwGxD9-+{=~OCeTO zlq<*5`7sSe)Ip@Tu!fIfc-_-5x;Khk#or^6lqDl$5S)EG!s9NYG0A-d&39~1?^BKe zsw3&Ya?;q95673|M$z#Rj#G;$$I&GlRVB_a2y7GC+yKn@1WV_0%NeIoSc5z-bNkA;T`9Gu#1xW>9LY1}CSpLd&upk>cbG-lWLxN1}8ZB4=I2 zSSP1&4X=ollBDP6CtTlakP2%VtbNMn-i73%J!GjFX+WcEA3{f4*n3t%Wf&tmvB^iR zMlVIUxC()IIgCg#Txz<3a5>aKltp%!;j9;)qRKx?K{t22I%QPSmPV1O*342S<%H8i ztVjAe@j+NzbtI3F3v`hX^$}1Lba@dv23?kl8o@9udpxS-F=C}m*Gt7Bw8X+#^eBtW zI9xdcJ_=1j7SM#3*d8GA^g_b-3OgB7{6Q9bqQw!bg;hTXfdk9rfQ7=AH@xCcOfF0* zQ)S57Y8S^!4dy7Mc;#?GEaB050Cu=Y)=Ek^P7ErchmC;}io+lQ)q`>J8Bznv52K8d zQ&h$SNQ$mZx2|~U+KF8S z?lDiJ5lY9?c#g~prU(+nqf|nG)=yG5r7EI&c?5zm(rWSZZ$x_HY$;C|!iszsEmYyb zLbf!i*co<#qREFV(hI%NB&KOfVV?qjw=Jpf*nH0o4^YNn0qJ8sMvoe0lrS@b8!LuI zx6^Vgq!^Qin5>(DZHP)JAVE}g=(Jp#0x=sIG!)1#6|P9WAS3uh7>a6HR0i&`uz;u3 zin&=pnL4d$U2PW2A}1Q}qF2xLhDVg&Q)Q&4%w&G0qNkqVvP@o+*T#wA{V z6P-(6hq1c_E?Xdi+xTi45V>$3%5Po(v$mGJNs(ffNF1Y#A`3a05oz&(VTwH4Wnow3 zi!wXrAfrvq%QRfFcL&_mF!6!s_RJ%FSEYpDYk8MIELaok5vSPGWEf5ke-k26gbz`M zy6NUF63bVh>w6C&)|Zf}G{r`IFrS5Q@Gz_BO*p#rRn#tAh-l4Z>7heAHlh97_aoAM z7&^~O`GPVmA|2hZ+IM2#>b0o(&bLsu;6{i-GHEA}__v2)zq~|zg5UN_-r^`^&_l$> z9b3`-($i@8!{hKxJDa%Z@uy?QC_Tl400l*P7sVOYCKka;XePEQ({P?9%<9Ss-gXSI zg{A3jCK28uVM|Y+0q4pEaIg9tl&f!m%~$f;>tL2w@}3#AzVH+b8px$VN3OjB6JA<~ z*iU|nWUPb>lt&~ni0&6(MABd=lecvI=n)jPA7Pl;NEt=2$4`UWbP1Bhl@iw?=^k|b z=2x%>J0(jVeDzi27ypGsZwNtRO*#}q{`@9nrkz7jrq|J%qkU~S{LptVb{0osAxDRSSL#d<~!TLIc=-MOOwgWBO z*fAiokt>|Ha3?w|h-!_Pj!1sOr{?p?^OUW4pqmm_95A7m6ypU{LJDw^Y&91h&`06&MA zvhqk~GpM9)F+^_(iMB(b8Ez54GKM8-e2gMTV#%9uckcCgfaCR!op=!%zjPltMVP98 z6V%o{NV3L>tbG#$YuBNtt_;eI^H6c|rKtE!6RjMhqR3Te=mZ2oqzBnd#bf{JHmYY7 zt$1H``Z*ZC@EJsl%3=8STjmlQ9Z2VgBwctCt<&%QB zNf|;gR>z?DMC17=a+w5FA!-W_lqF`Ex{xV!DS(STGI$%^0Wj+;=|*2eGyd)K6m10$Ls!y zeL14D5cV%TrdNr3qFr%X&mWz6!C!s!YPjjFa^0H;OhKMPn!ZgnIR*@K2j6%K=AGP7NQ?-h{VbRcw^eMB3G5A!qAS%$JAQNE5IO z#Bv%2b<5icAPQOreb%t$AT$yGbaP$x_M13f9V%Tk%UBPv@~!*9kFe{$dr_9?L0NAH zaxeT*;zWoZlA;7)PMd}a4?X~IsZ`WI_#h7S4#HTrnqy(XI@k&fFawHR4J2mW6B{t; z;qM?+S|a;Vfu;*l`tu*6_n}9iuz?>YyY=m2e~I3fMgf`Tb{H}6Gv3pP$dOi-a2=i^fgUqbhWbr{*c6>6eSZo(O*5Q*2wShX}7mrZy7 zmA9g3#sx^MT7~{S%?Kn%n0+kx>Z(z4**t`%vE0y$D2r-jyn>sZjF3F?uDQZ++TPXAewm6zkVu)yzJC3-kBZVB1y=0ZFIE6}>+6QeE zpra~)Oet`y>fQ5Yhtakg3WG_2nd+dLF`e~}PuAFt!$ ziO?3|FBE*?!HVheCsl;BSal(aX|C*vi-i-7K1K1g6jA$As94D&^n~&znp2Ydvl0Hp zpI^a(>#smbNs+XgPi%p(?Ly_KNo7o^_%=aRZq8A~z%8k-$Z%3UNwK4&2P>Cv!tG!9 zG*e|U`#BC4FIt6IX#|l-2=jnjd0cwM zENoaWdg3`;ekHYG@}1|Nehpv0=kutoFZH^O%6k~C*S-*g+`XfhalaL7-g-w`^wHnk z%|T~z|NVbr3suD}w_S-}Kl;D8{f;ZKZ0S2Fj+UcoPCcG|;uYL*%N1xR)!wjf7ykKc zH(}5A1Qx0rvE=0qSa983eE)lo;qLqHL_>NDt$7Pt+RF9QQ4`Aw9J8{RI z^F2x8r0k;}e-oX3u5#DWA=VHnbRH$e-#3VKI*WA5!nmykBS`qZb;ez+Bf4|XD-VLz8uaP!_Sl$SQbG!5+Dc@&45 z6U3@wY0gST&Ok^BA| z8j8_zxD(Zt<=DNu3*#q;v3FNHrq8Iwo?S;|<8IB{OHp1OpibkWsLMpTG5D zEPVEDiTEUxT+sjrYofB6k^}u)b%I#2Ol%dUR%-|~&yoU_Blf-VSw2y5GseryqF(2b zj~_p=6kY9kOqe(U`}gg|}3n(b7C@Sow1*)scFg%duIW=h8pFrdIDKyT0 z9B6GrYx4-pi#+cA#%=iVBVY3N)>uRiHH&?F5@1+Sjg@G+XcAstv>9{fPsZ%o zGqCXax0ns0sA;55Lh)Fz-J+s6s;VgskZX^hSdCZ-C*R+L#>o>!LIm%S+YAFodQr;7gr4<#>; TdTyN700000NkvXXu0mjfwSZ|I literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_karachi.png b/assets/uco/icons/ic_karachi.png new file mode 100644 index 0000000000000000000000000000000000000000..ab5f3530a913167ad1f25285b54a9cef0f46eea8 GIT binary patch literal 4738 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 Ef~^|_h5!Hn literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_khan.png b/assets/uco/icons/ic_khan.png new file mode 100644 index 0000000000000000000000000000000000000000..b681155d02f08f390b018734fccce1458951a050 GIT binary patch literal 6103 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 literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_kprogresshud_spinner.png b/assets/uco/icons/ic_kprogresshud_spinner.png new file mode 100644 index 0000000000000000000000000000000000000000..1291fac5365f2b8d5962b61595aa481bd3a98fbd GIT binary patch literal 3136 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 a{{aAzm86hS4_aXW0000 + + + + + + diff --git a/assets/uco/icons/ic_language.svg b/assets/uco/icons/ic_language.svg new file mode 100644 index 0000000..8103335 --- /dev/null +++ b/assets/uco/icons/ic_language.svg @@ -0,0 +1,289 @@ + + + + + + + diff --git a/assets/uco/icons/ic_link.png b/assets/uco/icons/ic_link.png new file mode 100644 index 0000000000000000000000000000000000000000..6e008086295a7ef6912a849a49cbebeda0804d07 GIT binary patch literal 593 zcmV-X0|WK~#7Fg;GyQ z6j2=h{ocIUfz88`3wS*2a9#I6)Ps$;B*-mT?au@5OfqcYdIVL~3xooq?5akLL{2aR5cSXeY8^rqf-SRs~tzrn}uAjYN7$ zz!*aqCSY#_3JZzm3ttky%i2?ba)fX>sz#a#{g(yn{wpcm(yEjj46w~}-J$)np$I`) zm3f3*UI14GY3Ds4c4R-qw}@atRk&UzGR(f9r56S3-V@o-G%#_SK>W{J?WP=Vz06RX zPj$?MjTk-O8*5Cb9}YpanYnJ5_DHQPsg&pBva15 + + + + + + diff --git a/assets/uco/icons/ic_log_out.svg b/assets/uco/icons/ic_log_out.svg new file mode 100644 index 0000000..92aa3f3 --- /dev/null +++ b/assets/uco/icons/ic_log_out.svg @@ -0,0 +1,275 @@ + + + + + + + diff --git a/assets/uco/icons/ic_logout.svg b/assets/uco/icons/ic_logout.svg new file mode 100644 index 0000000..31256e4 --- /dev/null +++ b/assets/uco/icons/ic_logout.svg @@ -0,0 +1,130 @@ + + + + + + + diff --git a/assets/uco/icons/ic_manage_account.svg b/assets/uco/icons/ic_manage_account.svg new file mode 100644 index 0000000..1346f93 --- /dev/null +++ b/assets/uco/icons/ic_manage_account.svg @@ -0,0 +1,346 @@ + + + + + + + diff --git a/assets/uco/icons/ic_menu_bar.svg b/assets/uco/icons/ic_menu_bar.svg new file mode 100644 index 0000000..91d0af6 --- /dev/null +++ b/assets/uco/icons/ic_menu_bar.svg @@ -0,0 +1,73 @@ + + + + + + + diff --git a/assets/uco/icons/ic_money_management.svg b/assets/uco/icons/ic_money_management.svg new file mode 100644 index 0000000..c66f9d8 --- /dev/null +++ b/assets/uco/icons/ic_money_management.svg @@ -0,0 +1,262 @@ + + + + + + + diff --git a/assets/uco/icons/ic_multan.png b/assets/uco/icons/ic_multan.png new file mode 100644 index 0000000000000000000000000000000000000000..31fd01286329d215d7b079c45c82738aaf49d4f1 GIT binary patch literal 6485 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 + + + + + + diff --git a/assets/uco/icons/ic_notifactions.svg b/assets/uco/icons/ic_notifactions.svg new file mode 100644 index 0000000..ea573bb --- /dev/null +++ b/assets/uco/icons/ic_notifactions.svg @@ -0,0 +1,142 @@ + + + + + + + diff --git a/assets/uco/icons/ic_notification_filter.svg b/assets/uco/icons/ic_notification_filter.svg new file mode 100644 index 0000000..8535a07 --- /dev/null +++ b/assets/uco/icons/ic_notification_filter.svg @@ -0,0 +1,83 @@ + + + + + + + diff --git a/assets/uco/icons/ic_pakistan.png b/assets/uco/icons/ic_pakistan.png new file mode 100644 index 0000000000000000000000000000000000000000..5778eba8f3593f20a59c49f6715adc8e3dfaa51b GIT binary patch literal 22980 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 B|0n + + + + + + diff --git a/assets/uco/icons/ic_phone.svg b/assets/uco/icons/ic_phone.svg new file mode 100644 index 0000000..b3a8b29 --- /dev/null +++ b/assets/uco/icons/ic_phone.svg @@ -0,0 +1,491 @@ + + + + + + + diff --git a/assets/uco/icons/ic_phone_bottom_sheet.svg b/assets/uco/icons/ic_phone_bottom_sheet.svg new file mode 100644 index 0000000..19a7520 --- /dev/null +++ b/assets/uco/icons/ic_phone_bottom_sheet.svg @@ -0,0 +1,474 @@ + + + + + + + diff --git a/assets/uco/icons/ic_qr_setting.svg b/assets/uco/icons/ic_qr_setting.svg new file mode 100644 index 0000000..8204123 --- /dev/null +++ b/assets/uco/icons/ic_qr_setting.svg @@ -0,0 +1,277 @@ + + + + + + + diff --git a/assets/uco/icons/ic_receiving_money.svg b/assets/uco/icons/ic_receiving_money.svg new file mode 100644 index 0000000..f77d07a --- /dev/null +++ b/assets/uco/icons/ic_receiving_money.svg @@ -0,0 +1,481 @@ + + + + + + + diff --git a/assets/uco/icons/ic_request.svg b/assets/uco/icons/ic_request.svg new file mode 100644 index 0000000..bac79e8 --- /dev/null +++ b/assets/uco/icons/ic_request.svg @@ -0,0 +1,315 @@ + + + + + + + diff --git a/assets/uco/icons/ic_search.svg b/assets/uco/icons/ic_search.svg new file mode 100644 index 0000000..5e0aaf0 --- /dev/null +++ b/assets/uco/icons/ic_search.svg @@ -0,0 +1,104 @@ + + + + + + + diff --git a/assets/uco/icons/ic_security.png b/assets/uco/icons/ic_security.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3c90def53f7b56e62bf3ecde567327e1356003 GIT binary patch literal 6995 zcmV-Z8?5AsP)@~0drDELIAGL9O(c600d`2O+f$vv5yP z2k1sOy3vhpbWsSq!s;Rn$R!?M2{ce}KSQ!*O9WhMx+FvCt2K)iK~#YyXNTPG5;ubi;Ef zT8tTrOAUcv@Xt{;m%b%|#d&3Trenb##EVQpADM=G`1N8W2#%sZkkFHQ&Beda4bM^t!v^|zt^;q(?Q0Xz*S#NAozVMZE$E2p9-y5S141X-#t zoeraD%x-9szeatGWTj>Wio+uWuIk zfFmXsZXr<}ZNM?T?&@BToxp2agjS<(uvub^5c&!!Nq<7I{9beVJVZWrneiDkKS@j5($yc%iYUYNzUpUnp}@UucTV{Yz3RKg=vPsbPvIp?y! z94}KXT_QQ)g znIu>V8ry%9lhLat155b=r&!&?-=7!Nh1kHC9I{u15>1qsp?FSl zB{)Qj#CZ4&+8HXWh^vsNtXRUjjKB9b6bnNa1qV?!9H4eOjt&U?P3o7P-Jfwj2h!@A z0vrwp;B&gJYA6v^YSLGhg#v?WnlRd`sCp{xp%R19#UQUo2G`s3X=Yu;KZhoKqrjn2 zfj@OnCn7&1fIB)aC2FF@BoyO}Pf~NQ!_U&@c*k{0P_$w>9Smxb?ytG7FI9jkyKaJQ3#&OGuH0R%iU*F$E8&p96$KcSCh!nh(YOR} z`4c}8er$y|cJe`7TbHqIZ}5Gu$uD!J*Rx%(@ZJX!y`F4%K!!n!qCg+Z3nWftdrnmA zDwiR9kQRCG;I~F-0k-qv+u;E?yKhg1xK2@DfNxN}D@Zr+1xIzF#C;Fxn=%Ys7s{l*%fUyrqAIr(h1fZZBk^t~3+&5IpU%OwK0lp6zy z4sEm;9}%W(l(ct`_r6})gu+mph0fSjF-Q03mH0kc`<;A9G7%b2hU)O$zKgI0K7i}s zgh(Sk;+x+ikT`Kk#QQ}P#@gAmL$_mHZYIuUr_7KE%w`i@2l;s{G7KM4t@>Zymj;ia zXrY!Kw(Hl)+(%pc-MKw*&X7f@-c^^?g;W(z-S;XgDhh83t-8qJNsvgta|Anz3;R zoD8Zcw%)m2V9_v#f}Z>V0-Tu_u|4H>s$jzPc|hQH)KNEY&A_pw*a%kK(+D6OZN;Yn zsAM&5Yxy^V?ETkX06Od8@ zt2iMFOsA5S{*r5o^3OUl)T>BNwtNl+q*e5f`WmvUoG~@iaTtkJ0_lv<*tt&sk;~g% z`BhjUmY^Ofg6{-Y0!(-s&5;Iv5EFD*0|&x6*07E_c?0pPxB*Q_Arzsjrr}5qWqU9eg3MNz@`7N3s1Pu47m6A&&j6ZS}p$jwqyoVl_G$>fN>% zU^q>RH&KiDq02RT6W>eOyB`mg;vGMh8P5o8hVle(7@5)8P-~X3c5fvNfl7-0t2p!T z$eCkWu6!NoPO!ZgBd8zUz$NEgw$H89{SmpuQgVo;;d;D(fJbY#Cj<@`<3@IW0l&I- zv#~)Rt5_ngR}btfyCo=Fq|?$ik&U0uKaYfaRIxvAp^@fpxP)s0bLJ{l;y$=TBZ<12 zFZCPF*yqTuc3>X_2_39#z==VDU+{g-cEi5S`haVxX1TKOyCQI#Vc;_)6Fsr#!&NlN zlT9%^*tZ<(;1kp)uJH%sn=u1ftpU{1gc<ù`91TF9hYF1Y@;GzJD#1}oqQ60c~ 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 literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_select_contact.svg b/assets/uco/icons/ic_select_contact.svg new file mode 100644 index 0000000..b658f1c --- /dev/null +++ b/assets/uco/icons/ic_select_contact.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/uco/icons/ic_setting.svg b/assets/uco/icons/ic_setting.svg new file mode 100644 index 0000000..28d93c1 --- /dev/null +++ b/assets/uco/icons/ic_setting.svg @@ -0,0 +1,291 @@ + + + + + + + diff --git a/assets/uco/icons/ic_share.svg b/assets/uco/icons/ic_share.svg new file mode 100644 index 0000000..77b20d2 --- /dev/null +++ b/assets/uco/icons/ic_share.svg @@ -0,0 +1,261 @@ + + + + + + + diff --git a/assets/uco/icons/ic_share_qr.svg b/assets/uco/icons/ic_share_qr.svg new file mode 100644 index 0000000..4873e3b --- /dev/null +++ b/assets/uco/icons/ic_share_qr.svg @@ -0,0 +1,129 @@ + + + + + + + diff --git a/assets/uco/icons/ic_snding_money.svg b/assets/uco/icons/ic_snding_money.svg new file mode 100644 index 0000000..a776adc --- /dev/null +++ b/assets/uco/icons/ic_snding_money.svg @@ -0,0 +1,363 @@ + + + + + + + diff --git a/assets/uco/icons/ic_sort.png b/assets/uco/icons/ic_sort.png new file mode 100644 index 0000000000000000000000000000000000000000..507212e2211b052b27cf93ae261129fa07f6e278 GIT binary patch literal 436 zcmV;l0ZaagP)Y<{0?q9>*!Z-b#N9(#X%<*7bofF;t-M$G$DzP zgOHY%UUNx%!~279aD96`IYQnffDl3m(K2gt!t=cSvMi5bhRU+6+bD|e>XT!kecvAx zMe%_tC$mBYkA57-U;h)m`mb4*ZNaR-f9$HNcIy*kq0=;d-i{<)L&AY z& + + + + + + diff --git a/assets/uco/icons/ic_sub_accounts.svg b/assets/uco/icons/ic_sub_accounts.svg new file mode 100644 index 0000000..2e69d4f --- /dev/null +++ b/assets/uco/icons/ic_sub_accounts.svg @@ -0,0 +1,239 @@ + + + + + + + diff --git a/assets/uco/icons/ic_tick.svg b/assets/uco/icons/ic_tick.svg new file mode 100644 index 0000000..e792fa6 --- /dev/null +++ b/assets/uco/icons/ic_tick.svg @@ -0,0 +1,96 @@ + + + + + + + diff --git a/assets/uco/icons/ic_tick_option.svg b/assets/uco/icons/ic_tick_option.svg new file mode 100644 index 0000000..3fc28dd --- /dev/null +++ b/assets/uco/icons/ic_tick_option.svg @@ -0,0 +1,150 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_cash.svg b/assets/uco/icons/ic_u_cash.svg new file mode 100644 index 0000000..71e5d11 --- /dev/null +++ b/assets/uco/icons/ic_u_cash.svg @@ -0,0 +1,186 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_receive_menu.svg b/assets/uco/icons/ic_u_receive_menu.svg new file mode 100644 index 0000000..397ccc1 --- /dev/null +++ b/assets/uco/icons/ic_u_receive_menu.svg @@ -0,0 +1,221 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_recive.svg b/assets/uco/icons/ic_u_recive.svg new file mode 100644 index 0000000..2608645 --- /dev/null +++ b/assets/uco/icons/ic_u_recive.svg @@ -0,0 +1,181 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_shop.svg b/assets/uco/icons/ic_u_shop.svg new file mode 100644 index 0000000..0e11c73 --- /dev/null +++ b/assets/uco/icons/ic_u_shop.svg @@ -0,0 +1,174 @@ + + + + + + + diff --git a/assets/uco/icons/ic_user.svg b/assets/uco/icons/ic_user.svg new file mode 100644 index 0000000..0852680 --- /dev/null +++ b/assets/uco/icons/ic_user.svg @@ -0,0 +1,216 @@ + + + + + + + diff --git a/assets/uco/icons/ic_utility_bills.svg b/assets/uco/icons/ic_utility_bills.svg new file mode 100644 index 0000000..8f0813b --- /dev/null +++ b/assets/uco/icons/ic_utility_bills.svg @@ -0,0 +1,269 @@ + + + + + + + diff --git a/assets/uco/icons/ic_voice.svg b/assets/uco/icons/ic_voice.svg new file mode 100644 index 0000000..1df121b --- /dev/null +++ b/assets/uco/icons/ic_voice.svg @@ -0,0 +1,116 @@ + + + + + + + diff --git a/assets/uco/icons/ic_wallet.svg b/assets/uco/icons/ic_wallet.svg new file mode 100644 index 0000000..ce25941 --- /dev/null +++ b/assets/uco/icons/ic_wallet.svg @@ -0,0 +1,217 @@ + + + + + + + diff --git a/assets/uco/icons/ic_warning.png b/assets/uco/icons/ic_warning.png new file mode 100644 index 0000000000000000000000000000000000000000..d2c8afaa6b62fda155cd852e395d18cf7cd8ca9b GIT binary patch literal 3227 zcmV;M3}o|(P) zD?U(xGKGRfv?^6Ts;nqJ;-yfNsEH5c70*<1x!r{$91jaHsOR18!66=Zw>!W5aZrUi zvpX|8)3dYJpMNOm-~9SZ^>?~wdb@i7g+ifFC=?3Cu!H;-;3bEenrbpaOc6v=bYLQw zM}lY+F;@W?0bmRO25=a_XUyCOq9b5FEP#Ew5PL$v?wWY~kgxv{4=EV~q+_u&^h{

F%jov@w9NY5B2WhSaK?

b|~9nE6HmegL4{Z%xO^g85wrp4GG2 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 N002ovPDHLkV1hEs=7<0Q literal 0 HcmV?d00001 diff --git a/assets/uco/icons/ic_water.png b/assets/uco/icons/ic_water.png new file mode 100644 index 0000000000000000000000000000000000000000..94c64c888aa9b701853d9c192638d8c4cd367ec8 GIT binary patch literal 2144 zcmV-m2%qHz3o1%1^oXc4P|^17lg1O~~ec>N>J9OM5SRL%F3Z zC@$)@5KT}rvf=(D&KCMZ4Ge|>(Z%Uxuobf(nZ#1iwzuDR&b#NkB7xf5-k)N8lJ@)V z`OeRC&Uw!JzUO5s5VC&JRMF0HCXR5jbsuu`&xiFR0aD|OWPRP3G1j++>6ZY1J z7vV9Lm^Y?7D)ItpjHggfWT%V-ln3%A?6}mOei7fMpFQrVbbrS5Wolz$ z;d>z+=v}HHrF*v0k}A*@@ZHc~B)`~jtBsYnhDR$pQZrYPbciIT^3 zvh`7vJg-TTlp_k#Fk7br8a^aM-+?sVOc}M96CLLUuU&M%5R17QE zyZjC1-&9ur0s|hfBCp|F80$5jJvEOTn_tg%jFDa8Vh7HS{-|89PKAmZP|`a_m&Ail zPF?%sZ0$_T^g1aS%dB>DpFcYnvH?bPg$KfqMOP`3r`V`j+_3i~jQ~b$g(VhVE3xuV zUS8%T_x&1LJ_2X4okj>FLRexIUxH+}k%cuF02cQ?{9EkBBT*Uwj0|D2591I$!J9k& zHt-uKoBk}qyR@Zx`N`0cTsA0}a9RpPqp8=_WgH~bUy0LlgYE9SmkLBdgwxj};7vM?O!H#|}h&3orXiQs0e6yJ#znUAPu28zZGsB(_q^``N|nXX0Y6=jJ< zPT|?8dfs_bN=nZ_5(6E`c^u%Eg1|`mW;ZvqwPxxsqlQgwWGk-Z?TY1Qt8BX!`k}RU zr7vb~KhurA&}`^Y+fsK;MzV-4kc0RY2)g}7H&f~8HN>jV6Z;v@+F3}z%rk74f^3x) zbC|767p+=?u`~5K=n6|>(P;793;6hT{n)7;dQ)pWQ=fjUe7Pe1JAUi!(!u1ynO7&;g#QS#=^zphFG3o- zxNhIED<_sv;{B-^`#y`seuX!;9k|$bz7@OJI&#R}*tTCbL>A(rxf?t3qDr>fMS-?SwP>)?mDb)Uecq@3JiAOzN|!c^lm87kG2ab63>a5-qh|v;}VW zyDYTFh&+q5)oZ~wBwKDk;Ij&^6(I4L>MyAY9LN>zk&hGRAPjvT*~7bG&um zyEzk1cX-d-Q8Z!fEg1MWh{~SO$+qgj>Up)1B^q7~JuasA4=2+(q@`L7k|*w_){ep2 znRvL7MXfZ(u68E5hqaI*b0OKtQ4 z$iR zPXZ^5jGx9ogLH@1x~JcmvmvAYk?CLz2dNHUld?QPyJ|Axky0cDEylx8VxS49PrO$H zGby!qOe9rODI&K(7Gc)>)AuwSk1T^@xC>i>OC(Q25wtt3+lI~ON9g1=>-g!Xv(DUL ztj9rM)uppB2;fM5#>st^L9j2XXg6&AUy;`Oy<6YXmh&|~NZh4rDy}ag`#I6Hiw!(g zLtAq;ZT*_aG92n>KwvppK0={+XE>3tlml`OevpBj?`nG+4nlAX?j=W^%C@am>dj!^ zG40jFW_o}BfgoncDMZaF9)^$Ks1+T=4Y?9q^G`UErM#)-@7cEJQO#XR+jBK$VtPtHgXg##vy7; zXiqo6O8k%VfYdA*XIL$Tp6`df^;NQEX0~l}(lA@S!fKOH%#TQsj6vvl1hP1TQ}eQd zlQD`(-iP;Y{H2gHK96rNDWNxfV-GmRqYiT7*_>`00sapo WWne>V5<{^70000 + + + + + + diff --git a/assets/uco/icons/ind_flag.png b/assets/uco/icons/ind_flag.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4fd0d56c2f4b12a4de42095aee1f0e3eece84a GIT binary patch literal 6678 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 + + + + + + diff --git a/assets/uco/icons/sending_icon.svg b/assets/uco/icons/sending_icon.svg new file mode 100644 index 0000000..a94f461 --- /dev/null +++ b/assets/uco/icons/sending_icon.svg @@ -0,0 +1,435 @@ + + + + + + + diff --git a/assets/uco/icons/usa.png b/assets/uco/icons/usa.png new file mode 100644 index 0000000000000000000000000000000000000000..9de5283d6e64ba92d0481a25f853b0fd60ba143e GIT binary patch literal 24439 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 LPhFux&LZT0Olio5 literal 0 HcmV?d00001 diff --git a/assets/uco/icons/use_flag.png b/assets/uco/icons/use_flag.png new file mode 100644 index 0000000000000000000000000000000000000000..ca0eadd296411099b6fdcd1bad8e28a326e58d7f GIT binary patch literal 7268 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 + + + + + + + + diff --git a/assets/uco/images/img_debet.png b/assets/uco/images/img_debet.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ff4bf9eceffb901ab2651ea4819fabd79acccf GIT binary patch literal 1271 zcmVb>bZnkNKG^I)NT0@G47EB=$`l2nCmi^KX)k6EBeyDv=3qs?yw3e14 zm{t*m_yj>we0)$;i0=nJh>~npli;dg&^!#1EZMNh`a5wq+^qL*vg^zod5Zs zIdf(-m0~L?DJgI|oy#>%^F|_(Dn`GWn^R=M6^vz zOl(4KLmokX6Cb`so{K{(eLmmTM0RW{dEgSjjw9|XEG&GZv$OM0JRXmR6WiII>OdecWM(TV<~21n z?=sZ0r+Q2WyMJspTLa>U$W!|E_VzXCGjnosmRQ+KiaDV38O|D$iST|5^PlLgfK9Up z^Zi7s&dOd=%rQ2H;clFIGY+&w^WcTJ`S<8^RXV_7HVlxU2$8^D)DL+e1+V|tQL zlCvQk4sW%xm!XnqgM))1m&?@y(`L^2rM|wt?*9J%A-CJ@fZ;Wc*kPH+sd!zIjlPaL zu;0pFN)?VXtYdf;;{S{r0qqby1?VLbZyAnA_U}T!ERmg*z@-t^x7CwOpT{^7?QZ&A zbUNp}#cZ8a$k^g9+ynHJd%yAc6qy^mA!g?e)N$c3|uajzwFypyvmS=~n8hI|HNVfL*6 zV-@J$W3;LhQid1vUv4x1z`#IbZ*OlfYPXrSpJJ=QbS2DIkVvESuT_c-8-LSpm6n#~ z83?UHHy~Rf-_yb_Pov!2+>h{V4WHl4^b$$bVEqbq&UJTpKay{Ve95H&112#} zV{jdHd#%Ia*nkrYS-i;XAt+%R9UUE#7YdTz`sp%GRn9Wu=Rvl z7p3e|c6Rnr#Fr&8sL!`m3az-fcurnk-g#`_2Ka;c{~8G(b@>557a4zu17;B@D=VwD z+wHDIpi=Fm?8-4^eHR24L!kGmd4%l~ChV0YgZb)s2Z+EiL^oB*3+P&8xhlgmfRA8L zNFDHcz5nXEZu+2@+;bABo&^&6KjIyr*@%w3SS4Gpa;G<1y+)I5llM9I@*VDHKcd{z z8s8@kb0Ycq`Nv`X9rEv8U0oMcn%Y!_g7F^MOVw&35>3WQ?EQ}nIqcmDmBu#hB?IF? zQBhG3Vl%IkalTJURU+Ig=%14`msJ{@X>DhZ + + + + + + diff --git a/assets/uco/images/img_intro_slider_1.png b/assets/uco/images/img_intro_slider_1.png new file mode 100644 index 0000000000000000000000000000000000000000..40bd2c2a0211b3a2bfca94e38f80904a50f187db GIT binary patch literal 131598 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

EQ&>{IgjY(jILXZSNwTP&g?}Qv9VXlH= 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 Y%f7mqY0i{y=$k?bnk{+g~S!jf*o%=igskdvg!) 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 literal 0 HcmV?d00001 diff --git a/assets/uco/images/img_intro_slider_2.png b/assets/uco/images/img_intro_slider_2.png new file mode 100644 index 0000000000000000000000000000000000000000..3389cc16b54af414c3b86bf57a1510fd800ccc92 GIT binary patch literal 64543 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 kyvpur00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPP(095)yFo|j2#nIFz*`PqNKg<8_W9?W?*)hq`eaV| zVt|>^?97LP8FAd1H$?oJjnwJWytFO;(EC|P{nut)X*>*{H57(~o;3cAuNB=XD`cvR zkQrYuCN(8Q6p?x)M2JgSp=CeRW@?S-pm#!QdWQx?r7GR-?SHd&trL?vZdZFdEw4Un zMWm=_25J+;VA+Yv`mk>x&DawZx zI>ZPO3rNJMXHh~#lAUq|mP@phPhh!3-O+sm%Oz^2><)d~7iVC(1n*R{U6IfRG7u!y z<-@c1A+QHMv}YVxQW8Rhx72W?1_8XJVu~MvQz}JZxhRKFlE89VJQ7M3ST4#TWS{_d zQl*86n>%_RSbB^#P>>s`uJ|f_V7Xiey$@`0A)?zU&XHOI%{@{}a0ZnFkI*TW_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/uco/logo/ic_dashboard_logo.svg b/assets/uco/logo/ic_dashboard_logo.svg new file mode 100644 index 0000000..0fa0a6c --- /dev/null +++ b/assets/uco/logo/ic_dashboard_logo.svg @@ -0,0 +1,942 @@ + + + + + + + diff --git a/assets/uco/logo/ic_launcher.png b/assets/uco/logo/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..99993ae18bb0310902059d1252ad2126de77598e GIT binary patch literal 154588 zcmZsCQ+Oy%({1cz$Jw!M+qP}nw(Vrcwr$(CZQJ_ue&_aF^fNO(7d^GAx>i+nO}Lzl zC@d5P6aWAKthktv0ssKu<9`DJ?005jc_-rc0%<3v?g#(?jr89D1W3>P`#TBfs30l; zP(6)x_WJ;0$}i0i08keT{izQM0HkRzF2t|o26*`e{?EwV1qW>Vr|p)-+vKgBX2GSn zV?=+JaRG#14*&w54^fmuQf%Fk=vK@#xnupPn#hkJgNxwB47RR<+cQQid;-N)SR58! z%?}U20PM7nZSv7cRyO1Op2b^4B!qS5V*8^fENT)eM_pNc$-YBZIK=(tYvya`s~R+Q zREUHjK3vL(04eSNcN>Za^xu0fg*$KE-kqAyPCMLQPRWfaniOquOKv1(kRFNXSCv=)%G*J|BK>UImwXB!slS&R$cTSD887>?g< zYw9w zQG5U?897*$UX`jpx*A#2IWNTbqW7P`gej1@vPJ}kPyr1B$|!NYR~-nOfC2@kuMkz; zC+4?dL*RQ9eik9ssZjMcxJpPR{hZ^aqY zPY>>LmJ9P9_3&38!u{1J2%x&^_2|-2HE^4hq~IS69)!tiq0SiS6e&#%%^keY18~`C#v&xT zy}R+P3L=v9K|sJe3jjTB)~ z*S|#A>qi@YUuWfJwS)$XVd%rGwf6-sn-6?OGOH3G```;MyQ7?zDmDs%Af3TEug%1& zJYL3F3Q6|k5iKPhpoR_U=TnGeUK6Jc-If5!9WkgE3l9M{ZK~0hPsx&RS+Q@{nLe1r zG)b-Hp!HO~+8?v_D%pkWU-D<;UIKh!rjx3i7l(>&H^_0sbb%^hGBfg@{vi{Tu&whG)ELHo*JuVuB z7)p`$LiTpZf2;@7Lu@Rik)CDoLbzfFXK%H2g;VU+!oFsrQ-^o70>Yz66Sh{4c1q76 zhESp4Gg#+3^$Q5}KKeh9mY#Tll;izy#Fwaz9wc0vPg$@=P)RLBs7$bb>ToT8@xO;m zf)vadC6zH?%sq1vs9?jv_U{f{hJ(oSV=wKm*ZHnG%9$^D=g?q{~fl?bfaHQLIpJ{x+@+Rs{TiF-MP&z#8ipIAxQ?~vU0js6Fo zSVdT*0wr;tN~-I`2DyHcA`WORy@gxPoH-A##C|(Xpk;&p{f@~3(1=Sf6Lsx5?B_;^ zNfli70biHK!Ok+JGuSzY?@fU5dM1hJ1#fO)qrWHemGGteStishA8Z5#9`Z83FkP(B z0L=NE(7!cLwuqW`xID4Hk9H6+S_1gMOxl97qJLM0oDC4*@D>{hC(x_$T7LqcIjJ=s z2Ex;kq-%0}x_EY^YNVjHqz=UsfBp91C?txrcv17e%jk@}a#h86arAc7m49bxtv2or zIt9<w~x$JcI0(7YEwlg<*1-;lF3}>JHsJ?y~AHH#lj7ieD!6X4d!xKmn73 z6#_s6>nML`cY7)YxI}+M$o=$O{ZVQMaa-k(GBPzfR*7p z_^^}+W0RGnEX2ie6r*Kjvt3V2bmuOUd)x5%M7POmV5D~*+!uL7QZi*r*2C6NI9N3Q zu`C2FpjI0*nA^RuK3}AbSP}zx>0x|sMpzDpk4vXyb#JQg(*#JnLQ=1tkEdtwe{d(O zY{$ntsuj1{OWX;DGE%|H25%s$Mzl9+W40SO*E3{&Q^GUFKyBMxfk+ zEO}FjNVp-M>BDYC|AITF-`%O|5tUT>LUU=E05aKf3h7YSRYdO3?JjcfpZ*;*!B#a6WLlY22kii$|JM=7NqdEL^wYom)upSutw6-Ed1Z0aj7yzd6mhw%=F{`IkmyP%CO`_nn;=$t+v`F4i7_W_ zj*!)smSUG`z39nYpLxHd$L-O_9*T^x*Jcr8mhZ>8O)Y?=8>@r!)kl08XB=0eZm7`NlB#Z2;gIxU-G8Cly;#xh_D!MkgeoN_ zZk8O@tXBns2=7&F0qG}mVgISy6XzzM6947x*FLhDNcSZ}`a~JJnS04-Wv51YK(wAT zRc2b7al=lA*Jkq?lv$$GR&#(`nM(OzF*y>n7U+Z{PQcRU)#i=6?UV|z-OCoh)r(hZ zTb{p;8AYyh*dFxH+*0VJLV_ZaVY;dw~C6~DTEO$+#THFyBI43~mZ`povrQS%}~+)m7P z6%#0acGa{k&4an#1k-&3mi>Ek(Y~N`=OB8Vt^L$giuvEtHXI{p7LfEVY0hE&QQ)9RVsWTuw=x!kWv2 z-3OOb3xwTGZgb1kYx#kB`N^t_;FC7S=YNV+`yUg?9ev~e{D~A9gr>Y;MddCrXNy1; zb~O~Z+tNLNa4uwLcVb9i)Di&b{;pu>?9W(Su?IwsZLeS9gij_WbbL_=e!CrobAUF|m&RNv;vNOrH|w zOVM<;)NI?$YSP#62uFh{c9gP)=Fhc@Ys;D6(^mDl06YHiX_wxB*w$Z1GpI4nUAU}i zjDg(=LVnX`1Mu}Ix)IE3d+6(PAmXZX6Fhl=Id%(39m4!4fhMrvjcjn5BWuF=>WVeL z#^ft1{}f8@#&La6Y61T`6P*7ecqqocQpSob-4u0rW}O#8k=FBiQ@OXIQ=xVBtKi!I z2M#g%+(5DI5cW=nAW~Vi8_TxiH`DauOpDJ0U84j|R{&LnLziU|M#fUh+#en475LeU z$w^INtq_Fwq6_fem>O8so$bJ!pSiY7C(CVhKOAE4?OwOAWs@uzo$v z+6o~zK(-rs4zIF8x5`Qg9#@)1is`#`;E^?+#I4K^ZlNb{FdNyVk$I@r1)!tCrgn&7 zv3)T7S6Iz=t5O7#S#-nw zIU;XeTeg4%d@NGOw|XF4U#~+LdL;Mv|73L_69BZ)<#HrBO!A4Flm1{^l(g?qmxM?v zwxm$p|H3xd;~!#WtJG^znM5!rj zC#zDAe?Rf+8R38-&Oeh>b~;6%n*W{Rr=#M4nfdB7}9^q5%6r9rO@W2aq0>+ z2-7F5wJ#=X{^g`(T_ae?R4BgFT;9lbUCjl*TMY68A)Q{X{5C#pAly%)>MIyLQgsrT zq+uy(cjClJS}USfKWSBV?H{-<3B04}mVb_VwCJg~FK)5=m=(I?Ub(xN&H&yM-cyk4 z^DaZ7j(xDn>SMg)X+ECv?IIWtB`K76!iq)4GzV8ytX&tAzo!n^Z+K$n4tePq$v8QG zB8wep#{{J4xM0=I3jg{?@HW%hwOchP!gR z8_WrmdW1;@5waigwu}wN_!RP!9ve7I6-dLO9HLD0iu>m3Yiz}aDkr@Pq+|coqn(Ax zAl5Hqcu{}Z_UQS;OY0x{?rlo5wIhHwA<6+BCzKlz%Z=mv?%r1HN0QPt0-+F?HYzh7#LZp|2*ulA8{B9TJ88QJ6bC@O+sAKemaN=Os)&*vI08e zNS_=c(H^_xwrU&nvak$6B>?X_ukajtIqy(_=Mc`y z<^Vgtqnm8Qj0yxasOkt$6@X2z#~$KA9wI{LPVqqZhuwYSu#q-V-)51py>xHslu&c% zh$xSEbBA7#+#O~(P`!HImN8@xPmRdfzb}Odz+!^a(k^@|p1ZHmX882pALIk~NPHYg|_J23ZY=w#^yZLNY#elxHiiQCp~P5bp)qZRlIuHS!Y z3A)Cp)_1h+r}h&iiXP^Xiy3|W7DthNwkc^3o@)oQZ5_ilW-=W+!Fb4#;IN=KDbP|50ZphT8`DgP)=sXnt zVfW2P&$<^rug@+~324xtrkKVhrXk_(Qx{rgnsqoggu&XD`&Fhgq1lrBz&oVe1b+b;VhW4EmF6-8|R&8 z^i1W)Gnp)auS3c!l@c9z=vf_V-)QvO4tH2}7i1wKSRF6O&q2h+31cNQqbgURhO{Ae z5NRd5>Yusm?s-x^Z7-B&)fIhD>#i>E2(S`*(_$vAkr1VaH268MgSUDF&vSdua3 zWARc1Xl%8f^b4Ckj)Vs&w_wXI89_~iHCkoG_tTYT>*pa`WGtgAxc6&qAL1PED)OoC zYF0J#!(9$63oWEduOjC(3bc)z&KoQZc;TE;u@Il*d33Oc23oD%_lG$(5I99S{*R>P zopOw_{{FX(7+NSv-S3u^--I4r{=Y&2Hz*)q+gqq_=?sOc;gSRU^|1{x3d&WT$^$f; zv+M)`-F|OWCOV?Bsh}eVy{!Z@A@A$)J%<{^VYG!HSP$q|FFu5Vp|30a?DF`N4T$_^ zbnoKE_}ewIU?LJ{ot42Z$mXL&uk^Pyln}I~LpXkIB0DSkvRhXeN#Nq}QV?Vq6}Wf% zDA*K3JM^tum5HJT>Mdthd(z%;NojSP*;|V;OQ7ayE=wda+09`dx|4B%prpw>8%wP3 zK>wu9(YVW$2ew6#0_LaT88YyKN?sJ+34ggHSL#I~F<;-EvVF*Ho(9$ZTM0uYmL2M& zBk_LSQ>J@U2C$m7JpG zyHz?ZE13(>h*`VVVyMqR34n_tgtRJ!t3ZN_Sp=Rbk60|>1vFas9!g;5Yw=KotPde= z$BaCPHyOy7QUK?e{0O^+kmIh6!)d<7*O}WCb3v;-yvo+A_e$zXCg(4$b-+Hk6Emp4A|76swF+r;XMNmHlxPT*lilDvsSkth84|dC_s1K*c znN5!ubjgXT;PR03ho6I0P){kpm^43#tRB#k)rQ~Pk(G^unQ_W5?QQ;~lrw?})-tR; z4|!1%6?wukPE$MBB5zg4^m!H0O}{)pImyS$=owDnU$~ymHhJ&#uuWE?9My2jJ=*OggA~uS7s}9D&$7$30T?972+_H zRA3b*CVPD?z<89?bF=)s6^Yt03p1Pz+TategyWy(E&isBF0eTwr7GTHytS7YV2J7~ z;$e0r;A$y9Clg*#=8t^vR3s4lNj)obb!%0J^`1Fa$OB0k%ng1SMTj}mS)aAqZpmk1%wXP{)lwoO2&|3ae6-287C9fFF&<`^Lu# zVi5}PpRG$6DoCZ=rECYfT_{RxKpJwDMk`mLO=5thj8aoeMXxpE!6$v{+kNJ0Ea zzAn)=`8dk$OYp1_1i0d-gf?lu%nj=B`_+sK&}Kz(m3EteksBTUDe1Ymw!wbXnU_E! zRCEUe^dh(J9kUAK=fYG*SNb#9I|A^q+&UW66S!L&QhbSwBL)JP#Wz26z-pO*?huy| z@t%kZq$~R1Nj3-Ow6X?$stn}B3B#z^fMq>hY@%4J{td_{sz{#}gYeClVyv}(U;$ZF z?+$Wm#^IU;PEE84hKjbbjSZf5UnbjrCRgQ&gvvnI83sNhPn(y^k&uR`W=+$;8LZBx zVsK{Zj=5~FKCLd-n=$NSbn~u~#KkKImc_k{h2Fy_e~C*TVYW#TuGtyhgK6QKc2*g9q=*S zDe2ec1R1}%{^*_{@0ss=`f?rQqhOGB^%TQnqVZsubZGE~B0|{_ssbzykV|bf`^Isiu{=AiP$!B#x-H&Tn4luf)pDACrk5N4%WvKx-AT5LY+;v zkD|%=ti_ds6e*5y$SN_Z8m`F_=xIuqhfm4opLO^fS7m}SV;vuO!ci3SF$-^ZjEE6vxU%3EwV~?F z)RM6oG<+kMHJTomowk?h>yY%SMS=Ep0dY)Ibh!78GUKt^+L7IYKH%Re`sqw_>tlKfv=7VLa zl&%6-h9vgd8|9BI*)~+RceSEIah6Q6Z|0RGI5R+UbyjIDo{g1+NE2EmD)91A+h+4Q6nE(8KFAqzP z;yb1Wl9z~9O6*l$_$j>(VR*4`=d%Y;UlYt(5S$N~?`1ibn)u}=pD*~yfMOgr!<$5+ z8mqP53qTfLdbRURJVP1S-2LG`D@O>Qo{Z=?H=rEU=;j%RS-akF_GCUZ$jV=|S$n*c zLws;`usycD&uRtD`s=7$h;8fUxh3d|YOe|O!OECvMewrS2 zMjWP0lE^Ek3%1IHZrx=-TA8b?t~bwm7$`Ae3uQ~69{;qLPLbca)MROckI>x$+^N%B zm9g+H0=L960?56u8Bv4^l1HE?@A2As367Rls%J{&y~~gK+?ftkzrjHp+B$f}LSrZ3 z#E{+po_Ot^HF-EZAfcm)8^iIwC`rJ0?02lD2`%<1?-t#-s&to~biCU{SLZ;>^`;h= zx4Xq!QAw7U$M=ISPDZe3cq{{4&_xFRtzmc>o#zh4RmlP-6(cFZgZItm?sK_q(Vk&m zF0*+ujEu{7ncIi2YxRYAt@&rwLt}zQdfzcirk}pe+W)vKGCXzeJ1(TcGq^r(;u(%O z?n9egQojse#oE|ctZ=Gc3xIfEmX#rEFc-J>a4sdq3K1HrhuN|Aj3+%~8lzD|A00Q< ze4&*aq+0%*_fUBf)Ym;O{XBtvPonTQq=tLl|9b2kIdhfE)VwgF{!JJR2|^#by8|xA zGrXwG$upR9h|M7{KnF|B*;2wpOAXI}3XT0Y#6ieKaZw9REi45YOAG9?QtBFg$H zd}z*?Zu|EPhY|AxB}91^bjmppMplY#0ba>>M&m1DgQ zfhpluArI2g=Oh!k=S@ouVk%|TgPn&Ocp1ddr&D}-OGhwV@j}O!ogZJRNwV~! zN>V^csvsNTDs{Ui4F5YwhHdZFMg%_eu_i+7Jg%HsY&W-(yM8p0LQC26q}j7nG zL+;RfTO7_sUjIIQBiyB7EKa_i@pOKq4$HNqSO!q^(=!6O?{wi>z#_fJv%djadiihn zd4!d1tMVVMV=pqeM;il1J1Er=9xs+S0ywe#b}OzDU|?6FI}Tum)EO2Ntj1q-S%Z*@3dk*p`$gf7X-?@^Wba81fI7MT1)7yq=`~*;_36X;wfcXQ)WLitqjzZxm|mjaruvIHh~{ z=M+Wzzbtdm?oxxBXRpcG>=XR94I?pq$6v;+PX#X<5{sW@iJ6?wfzrvC!)B5T}sDSABaL~wo;k6JRFHR8$rG(4C5)N0GVTXdL7O}p7Fg}F7rSY~c2hvK zaG*f@P58c?pbOqF1r*>LTWj^}+GhbcbXPvtRim$!G?q`M8e7+7ra357=x^1#fAhy6 z!2jsHJ~qHZ1@9idDfZFF^sRdPYBn38DDmCC$SZ!S5+rZlA%&+KFxO1}EdJzyA-xHW z1?BM$&7WI={oLP(sNDD>Bcz?BnshLpUT}rG$!rn8i);>-;%x(&CVH3BWGs{sQFbZt zurFzv(h(o8>WBhG3j4`iw0E%gSCvI+1|>i;mNrP_^6}hSNf|48k`#|&9GJnOA~02n z>^sa2>>dnW6Ed0#h$BokFUiCsNBN zZ$en$36|+V@OgydW~pIQ54OA0XIw4kIZ+M1{>znhn?SbRd%}a)H^ET~u@v{jHY!E7 z3jM5q*$t>K+4{@jEple}0jLcb8jpur-_pilaFoTiR-F*w84w8=I zSIBL#)fwu>~E%bvi|t-xM;ox(l=Ihrjz* z-&K>tuxz2=C7SP>ThvDAG-)(AP>T@O+VUnl{2UWm9TT`Wg4vCgRjshz!?t(!q$^7c zQSO1M6;5&HqY=X`V2*HuJ&Z!+3_ac26vm0|#}V~kbrGXuYIzM4+XfJuwUEJn=s2mu z+4(xc$X2-uRW23^C_$L6+B8eiz7a+9FnmH2zu^OoYHeUl-waJ{L)|t6C`TKQ60>+R z4aWVra6I59NQcMl5kY%!0_44iQJzP*A-{hS^Df;7Zbxld!^ANWYKT*Fd!v97XU=fO z@Tm)`dFWUr{wJo9h7hM%OXJ2mr#Pqo9xq`iaTg*ZCleMN8%qD}zDdvo=;9M?TeRqL z*TL^QPvbz>eFWUElY?G|s$OKmi3VGfDP&VoyW~DtfuM(8oc13pG=xl=%I-TamtI!q zDhVic+qu6~wY;^g_&NnE?&x@2F~axLPfgGCrkF6tU6Sk_=P9V!kd|jWLc)&$#FlL zAW1z2qdf?NVbcI06&5vVm^IH&7-iQyMsFYkoLo6y%2P@a3=j5}LErSXXX;X(zP6JiNY#=u0bKYpAQW`gn? z_;BE;vL8_f#y(kU5B+$|osWAuf?VywD@k~ksKW>H)hf84BD4o-M9ZuDQ@S^tYyIzK-bxylY76MQ)jy++isd7d74TnbqJHoSP5%(EAY6t zoMj#V2&o0HwZfeg4`|&6qmD;jr%5cW$Et&O{0ppC4vMH6V5wJl=6nH807yMIW=~0K zaeaMCOW_?VUOkxU1mJmJ+R8$KytGN-I{)&;1xj7GkcyfgVY)`waqQwgiTqdGl+p6m z)W8ShuR@d*K;oQX$?hB&Ks)6D%W}PG4va3y2qXduSgE79CnO`HS5JFVm|mX+^K%aG-_8lP>V&FzsNZ zx8HtE%f5D*MqN_i1ybDHvt`l7L?0uD*Aunh2a@14W|m(AizB#l*S_)ZTs@s(;|1}i z28({jX|E?MhFoQPZF-9lDQ{ehd>$cjO#VK3D0gHCLQD+WJd4VDvf;YUmO(||lqjiN@qTtUxYPyyH zKGu<)4poDFCVGWjOlPJ7RSD({=@2}Wq^DjK1R}r}bX#EbDU~XahoTTE;}9-!SQ#flJ*GDWIB z5p4cZAv>XCY3E~d9{+_t_&5&e=~*``@UPWUy`(V#fsq0+UzWG^FFcn#lmdZ`*<02o#u-O}mU{+WV)R=O5p13g^ek}*Z=BuC7SEpFY z&ARM%`-EB!DH5hmP9pD=XvB@tCqUdmU7Jo=F7^b!h`ew6{^VqbQ|uide>NDW0$M8k zJ3dQ*%;g2WzwWrPfM#2IP4@u|w_UDD5?~`=X!xl(FsdE(*rGuTZ1a7X;InJH9x4k>#F9 zyRsMf1VlwuUfcRF>9I^O%)a6jIGfuZi`3mH9#iu&CwBL6i?65rie;mR*q3vx&UD(L zR*i}s*r!X(y}NH$-|S2U#pbWLNZi|=a7ULvlwt#1$!tpvG~}t)NVm>T15$e_$g$2q zP?Z4W)D+7ko*$&DA>T zL~x_~Pb^ZuIZLH*!Py^vY!EELA z!VW~W65}STYlE#A`e+EKX#WQCR_6^Hva(?_#)L_(fA_a1o6mVEsz3;1Vi=zR#qif) z8=QOZC3$W{CD@#~k(&#WNK(9*VrW~|2&EAZmkuv{@}KxMau6bG+0e%1Q>-d$ybs6R z@R3rV?NX-?3=WZ|(E?nZuo88h~`V!&boOJ{A-FC$UjN zu)(G8;WCb{a@C}fa?m+cGkkUf=8c8h%_xau%E?hH^jNK1@A{aVV<J5L2Y{dP`Gk6U|=`(er@R-7-{S<9R=OEOn)HP#V{&! z?!013I5E1%{++Ljh=Ct#(@3Tq{2y_krlZy@)PtaR6kkXP6K| zkeu4Kpl3hl1ErCWYmw7p2-QyQ^xs?bjKEF(H1#Xcjk@LW!fB9VJ2xKQm+dKtD@bR3-L_TuD3j^!QU%x8lW-NZiB9S z*De2EbT2=Lp(QA3zngc#`6>@&k5eKCeuG}#G1Hy~ODkIL1(#u_sk_s>cW#YzZIgOR zb6?sGD_1DQNSDuKcL{QsO`zGPut(%S17Mt@iZFYpOLin#$&|+CLP5wG$m608YJYl` zQNA{MEYWCv+YM=Qlul=t>ru~v!Z2$0-_GRw-I+mSoHv~XybWJdLRIo?S2tFov)(CS zE1&uB-)JM|mhBB)1I68*E7x?;x;-t!iR^&vs@?a*ZkqfH|4cX?yjKV$k?57VGolGE z!q4m&0)6b6h)eR#enuc!u!h5Z&$v#0-t&lNUjDrc8MCnyWaTFyOhS5vb%_>0z$1I} z{J;o@01}scoYp*9a$>>qh8}-pMv|CfaZ39bNhA%)dcg$|SOULIme_ISaI-=agFIhJ zWPOd{_!FnS2G7$ZD^L>(BT9+db(U_jwPs(qmZT_Q&kQ}J2vmp+qRrAC&z{g&a(ouI9H$oih8|gPFq27_s}3|?KOaXRs0tf{&wjGkmT zUjngv#uK*Z9z|AXJrvv)FJ&VfbgaG8dL1)GyLz3Z%u195yoTz$hUdCj)R z)N{hzb@Nf}Xn)}Q$(s#w@V4Q?bcywIrn~JQ&K3U~wUUaFy%cl{R0NT z(HBpEdG7ZCAZSa!?IM8{r`ryx&vl~jKTJRzB<09QF~mQ0xs}=_FoMQEBrJNQSbXiQ zp?8{1a50Qg1OTQd6RA$I=gx|U5S}Ypyu(vAY>6=gPN7wVq3J~SO~AducOe##gaPy{ zXC4I)pGyG9L|){|N=>uDS7!5=Dvt}y&kc(l5%9tur}$#r zp3w=%^Y5X)89>>P>GmzG*Z>PDF1x=D5;vrZ+`orl=!aR09X$CBaGEl*6y|l0ov@_B zzPr6`rvq^k3HHd?t8cmC% z_sO&^NwD=PZ#EX4+%f~cRbgiv*?QmN+ZLicg7U+4RL)WaCj9HA^}PIKXW^&K@f1SgH9<_AlgKYzl!3NrzEeW>Y-I(7%~Z33H;06fp2+@Qz%}w5VA4V3ccXQ*PpfnwxS6i|0auu7F+1K*SVT8FWlb={U z*y2?$nn`%9S$tU(lk&RHMU14ot8GYe8@`z z;RK3_fLYm;sL?PWEVv_9Ay#+m2~QO63Kgy^*e6Kqq#w$*l&wkrOQNA*STBd>Yde>w zAiPlM_VnEdq)NJA^lZBOEOU!#LoVC#FEWD6wMQU?$-g$gQzw7u_0{s`4?;CEWxE2H zNsePrKQD#eIl3z;;6S6ve=b{miaEz6^JZp3M?Qg06Q8x{7r0!7d=`ENsDGU8It2|* zT|JS3H5|pl`FB?2!NjAIIqP@hdA-5MwA8 z;%gBdv+BX*rO&zAZu%!_PSko>7HQvf5KF6yRMN6~v(&A0{A13EFtft=zGJjc717*h zbkvRl;vZ~p52FH2sY-G-+ZS?u=z3Yh;whIKeD689g{rio7w?CneM37VbCwI z;&-~k3YvGUz5o6=C?uZgH5@gUl?A zqR5b#26yhyi`>zUG|l!gWIb^fBQXwC(X}f^jyoy4kLA-692?ndy!TLQ5uq zfdN7Oxep{jz6;peWWZe|X-Y0~3(4^&2aP1}npkz=rC7$^o^G*G+8ZujyHlLo{`m&t z0eMBfbhD?2fi}n1VH0r%{g;>Oeqw)xJMn#R`q4!Xs`ES&mt@_3rpPm?Z#@VS`}}X? zoT!urU$@E|BVob^&w6ba`d%NCLsThgXIlKKTkaUEodaPH=G#P@lBFDS2)gvGCgrK^ zmGeK`BxV7ZG`u58QkY=qoX7H05=_TgYht(jf?>ifKdrv-kgtfV{vrominpMwu5}Pr zQhV1maC%?mx-||ywX??aCRdR5`1*O8lyNb#w8RO+yO(4p;*i(_lArRL*ty)JTz*Gv z0lx!}jw@--z)>~~op_q)Y4&ul`r>PTuEI+j9)LNaR4USeq(4XHwgNUesTVYcR`P;v z`YF_4^@Y_C)5M002f5$`WWJJbYW$4Z%iOaDLzj#roJIaZ#k29pIYVvq9MClj8|jy>_)h=mYDj~822`xeZD9f?w%vw zU(u{2(K^4swE%pDjeX^~F{3~&G1Ok=SaJlbH=ccQ$Vj1i)3>u1i5$_!S9N|p-QZc$ z>svZkOc8wov_2HWxNS6lb)A`#;ajx&H|~B){iT@<**jGFTfFb_la;@wDn8|3CDco^ zqW88g{m6a%@)`8k$-xFkqEzotVu|G;b7+hd0gm6xn?J*e;JjbYCn67y`yo^ z9yEpb6X6t{DIO>Ck*m`ldi3$jdgLVKm;fdfYoEwyo4YFk2t^>SNN>PUJxg&=<9=;{ zzB)tKrritYtfkNvA#f!yHN*~j^u1PFfq;y0ujl}wa~Vtn%1frFTpeeJMR}9ws>DA> zaitT?MT0J4tX4JJjr~ds=FJzx zu?$Y&>!V~VbAf3svA;V@!JWgq(cf}2;xR%)-xI>d@+$S(&gg6U#Ob!ruPuwX4x3l_ zk!Tsk5jKmqNbnXP)1;Io&Iz-v`CUifGv=6}oHSe>z+tp&+gWqFBSwd!y6*ztUCKEL z0}K0yeN)-Z{uu|lctUa{K3;=<{rTW+cS}Rstu*`s)bnT6&yN7Kh>SIfm^HuB2N+b!`K{{Y1!uiY;~ z5^OLJ>G9b@)_JJ+Xwq30z-cWSG-{t{#dk|n0+}1?4!|WZuCbt0ak7~RN9CeK z!Z-LDbWVCeHd2dA3C9tLY>*W3(>sAVQS1xy|BY$#oN2F?nnJER(M!F+3#+1x6F09k z`e?1epim@M(h9H2aEbF4SOM^r49+U$2?R{2TX=G{UK7h})jr&vkrOlh@nOP&jnQvK z@-H`zO7F_8vfijknGiq;KVsdni=ECzdWs@TDb5sehdPP! z{p0^4Nf%PNt=R`T8p8WiU`y|&`J`>qmk2OT&2FTgl-p!ZdMSheS_=Pr$TFzUQ#SC% zUM3536}oWu5>8%fgNoPEG?vxRVf?&EUYgf`_hkFSm)^^ndJlD!eL(biltR-l#qrx5 zXnO^Qjel!PT_eCyF6czjUo4YUKC~nuN9}I+-VX|~H>h!K*2y0~+OquvpM)Nn1Q-!; zV|1L!8*S$LwvAzSy26G|{LsjTMR$WB&LcKY|0d@1-1xlv>=DLPMtMs6$7g*eXGe4t zgHJ**icbzkjhT(dWzK1nZ~WV(1)MuHt7gjwF`b_^VmCERBa}fDQMw2(P1tbd-MRBm zMefCbux~@qaTzie!xhO6XH^IfkrHrrFDEA_up?=VxZemp>h)$IN%|gT^5v(f3WqPU&iP7?@~AZxE!0QN(l2m5oysL+CgL0`k1+@OG={8i?S= z7LTK{5E>y1{V;sS<7{J?0JCvqSOsJc*h}lcq3plMKKhA?%)5!oX}xN)X?%}RrhukH zoYKC8Kid9`EVJ|ix~X~vb5d*DGP-tJ@hGxwZL_^SIyY3rX1iE`sYnxn8ipH#f-G8_ zf>t0zI=un0XcNBh3R*_+`S|d9gHzvbuA2PZ5Q}f(qh288T_sl;K%A^Iw7nqpapT@P zx}i$=EclSfBw=Q8mX#8!kT{H>CFT?ke9a{)7 zx;bhhhb|L9f6Q{fwh_@(^{nC9VXx6hGMKl@G!7{Q=2WA4`PMR&@&y^iZacgFa*)Mg z%8snNUhRnOX;~qUCk-|^f907Zn|E19UQF62mqfjRBp~p6TX|pzk)NdtB~SF+%&!i@V1J-x30Jik{DJ zIp~(@}2h*(c|wi*BPmFYOl|S0dui;pY4FJ5zdJaFnBD3#(`qt z{cNJ*N-HI&3 zbKt-@{-uc=x=aB5G0NJT|M@Fky^h8*Kk56ueBoRcCpjN70S41ARU-vwTotnE z7(^oBJ(dBEB1WG$DF_x$pn8xCoC?b>Zae6c_f(rFEg5kvBi|{So+`vqBzv9KMUY=! z&$AD>Vm7IwCcI2m30;xq;x0flcD?q)1pUJ@|BtxZ9vLoJUamVxF&bC-5PP?C`|fS1 z)LpoGw~qI(iq{brWaSZ5@XC0vmUCNhB8kA&Ets?0_O%oPsbecZ)pV)EtG_P}gzMb< z9yidbj+azXaPEKaG1&sG*o2eZWDjw3&^1&RK;_p2$^nmB9rCdv&WKl^|Z<(I+xo! z+fYPb(!G2GQqd^PWzx(#Ra6LTbWh-NCgaN7_+f;4o-1L_J?E0F)d%s3Td;CBwBBji z#Lgqh1QbgaFtkiK&4QD9QybuHLV5a^iUQZnS!=u%2%r+z;-UC!CYJhyDcJ^&(6mc?O|~U#2byT^%;hLZPT`7MtO(G?km*O!z3}-{IFaFOw~*3z z+4&&pYbN%`+r|O?=nunhKGG&1@>u$b#*z6lZ{KoESjOwU9u&Kw;4;eXR*#1`E@a?- z=}%)G>2(Tn_jB#ckd{zax%BJ|cXF$Bw5p~1oU6bY1_Ppv3Ps(v;9J+OfT25Za#n#< zY`{U0qO2wm^Pk1%*+<{~9rn-H$`x2ReUk6})YNf~R2S|h?#F{fq6FtoM__)=fE7w_ zLlgYXWee7}ZLSedI`w8l_Fb%d|PJ&ED!776hcx_uNYxEdbOy z)wOmjqA6${pv5U~KHv|Pk+~XLB^q3L&Y?~ghD@`gaZoT4mrT_S?xAj@iIL7jp<%U4 znzn>o3y7ZzUSg9ZvzUobniCvq+;^Fi#)}FoQ-r zVYEb$#ZT2nh6HBpI3HwvRkak?joC_QQaAQ7$;8O`2;}zH|M{F2QQ~6tqi4{>9z($S zFFPzZzDr0d+>vG3+AS0U~Xy}w(c+QNnMMl(Iko%feWv`jEqKuNNl%! zELFFn8uPc_e;-*;MNXW-XQ1*5IWj-@RXF-~A6(8|Tze(D;)BSws!vu@%>vi7!H$#5jYdc+jJFrnqzp)R)&{J~tl0*627nj12j;a0kLy_ewT7V)i zg0H3F?LYbxFzdB;XE}NX2w0#0u`j^#)oXAM7YL%;r;jc1JzYm;PL`lQ`SU+#H;}5i z@XS&OUjI~#8^44)701poP`&riMYJp#=mTFstJ@mf{Lu%j6qDJV;y_55J@fK;(8C5= zlw{8og*)4!d0v|a$137df@0Z*DxQNs{ce@pv@UNuY;9{9peSH2hGUyTy#>{G2yw|+ zxx~2yGQbyq>c`pYuz2bi3@dmZws9WI;mLageI8ZFWO2{>>hYiW4_9F#k4z>E{Sk;_ zxQa?nVUMd|P^|0pFd*J3+}+A`xh6ZOq}jVnq}8;{4VtOA``eomyH%*Jx5DK?qf{bP z3mT`Oznqvkmr6x597XCy|3iihB23C0#p2rEcChhI+?(u8_IabnKL0O@&v8 zktaful`9jc`I9I6E*VwNldn`*h?=D+&@>gi4;226O!33iLu$v1fNVwUI`*DtOvZo! zxAj$m`sl5Dkc%7@od z^(xfSPq%jSwrtheN9Il(heS3DnZ*S#A`wU=6CCaCmbSpJBSX0NBgmou`&QnBsuG8q z8i%xJfq@f{)oPd8Av6gRvuUXxWM+5my(vPZKx7u?p-^kWdw191G@39!yQs78JKm8q zzSD5otp0=L8nYv6?Mjn5v2rFsq6-TjzzBz8=)*AcUfU33{ANEJKIneL;Ggzn==;vk z*bP{QId?tx;dftmR7(H@qXw5(Qc!N_U~i&J7&T+FR+nt`+!^rjUbN8UZs&J!DYVnn zqKP;cIy&~L7r71ZM<4wExh?Cb&qmtS{(6pq^36pA{Mc(yK@wz^EvH6HncLgM^_ev}n`u z)gK-E%m2v=Oyr@}q>SN3TO`HZk>9Dx1wI^M4tbnnC?O1novUs1@+9bx5wlwM-yWF6o`4ob|L++4;6 zUH2h|y9}eNicIhn3GewKu<-d+&^p0xc0eUU$>Q1`N5seDCjMo^$wdQ9%ZJUp!}ABZ zD!ic4OVbnld`E*vRSBy9Rf-j!Z+5nJ&^?Cks#GFqc+>xo(8?CWIpQKd&uhZ7)=)Qy zufO@9&CJ86OYm3!>ZAzGLzD@iKLjZwm}`dddB0JQ2-l1tHvU_qmT_IbzXJKqJY0Y8 zDgtMv4TSV0H1Q!@Yswnzoo!Adh-w68U%ixO)AFUo*aO>D;!~ia-@II?LOr+2KJLzl zT_cQa0SD}d!m{%g2f_L5kDf)QFtxNO6#z5~-hBT9SyuAZS7eXuNCHx76UX7h_Pr|H zzmH7e*djzDVVI*j-yn-|w1j(>JH5+6$1-W2aNfJS!6|NrXX2z2M$mrnwoL|X{c|Vc z-8Xg+Fh3}`kF&i2>x^AQW>_}d?>FO|%YI`Savb6y+vxmlmvdWgSg=!Z;k_Fhuu*W@ zZAU+I<}7;36ev)jC4z0G*nl(wcP18P_mPdHnA)|Hq~cNTRWNg&?m@EJc)iCFC<73A z4lQFYU0#JcieA? zYFMChapV1K9Q9t<-hqV^i*V_c=edKMA_n*{gm?wr0yrsnzwKJi@A!`TDYSlg%i%lU zE?>U9jdS4y)E|;e0R0fff9D_RcW97XJ(*`u^HDm_(T}Weg9U~Jv9*YvBvq^uT%u#25JMPO2iqfnXDhTMvjBE@2-U61A zA#N1&FlFo_GVS+|Sq?B3(eusVl^)umKO(CHS$)XwJeSrug|SqV^%S^mZr{y9Jp+h2Yt-0<`MlYChYEo{wGc+1wdFyH%=r8I9%!g6>jPz98ny9RlnMp6W<`a18g1*(Ux+}y z>_T|Wf^yA;Qq_}xS@y*pAuD~#3@*#yiW;DwAH z4;z6pnd-C<6wwE`apzvU8=A&Bw8%vCFq-!exRG_lrl(=){5hP+bZ&f-TV93S$||hg zy3I_Rg43wu6jjWk0Hm4339B3fhrrhA?Pt5T#X;g8}b(x{d zD0)SfZ$*=31I_g|{^p~b_tEEPbIv$*i~8KjG*7$-mR|nj#|h?#v7N&N^8>mkMn9J$ zd_K;$1_(vNQySR0#SqM8Jb3p8x}xxbyS1^={!Kb&z>DXm(0^@k-vF^M;FCa=+(r?q zsp=zExqSd#o8@3O$JRKrW8==<2VzY0WDFvi3{r$1cjUCPo99}^b{-{L(q=O3;?l()X# zl%a4@U4~7>@g0?or3#c}CCqPb!}Fi}6fB-ThL*C(z#i*J!jYxJEBpo(cj4Iu#j~zj z!v53Kjzgxp37{XcOaT3mWc|%Io^_jO74|F&GMz!x{R#v*n*D?(0II`I1sj4NSW1T=g{Ejt4a!387mkVxQ;IhG&YAgp zURzR?6@=&i|zSUcs*Mq^=Q0CV80 z(xe`v{1}|qo|y^5Y}|#Fs>we8+v~F4ghJ&r>G)|t!DJ+YJa>~K`l(hsGK?^~4xXQn zKq{hgkeezFidK(s-NV}6K@^X}mVHXYP(wKk9jv{LL$=fg+hsiw|5?cDkVPP;It5g| z_vhJKkaA6hWD4k4Uu)K3Chg%8f=DFEsh%D_SPojmwwCXpbu6e>=gTY;>P|?dk(UwZ z(NqSfXI*IHu8_X+WKx5(XTn@MHk(o5_KFSL=w>h-Imc`_rHf63e0GzCgUI)KxrQwL zE?V}AaPs_VH1kK%M<18}pbdCx!p%N9)JP-Ft= zhb1aJt9qXBJy*krVqOf{V1*0CphwP4d`%W-Cm%j7=V#E*k0!-CSBm^vsW)I)$>Q-*uK1^yq8uq4 z9xDH6|8Wm^KgznjK6@DZ?y=6;V1AeufY#fC`r(Hh%fs}Yw}i~nba%~Xq)X@clzjc+ zE!i8s+LXXZfPSx9fh)@<{x%CK^qFT7z$q}4fSK#Oqkp?=(ZJ4e5TGkj*j|;*Upni> zQ^mPBK96@c&>B`Q!sjolFoo`>XfzEv?#C4b=ykM~t>AOqL2@Yz2De2;Z8p(rW;zu( zmW>8Vez0q*Cy`JQ)Kv!an&ENjdU&068@EjX0 z%=jb=|KH^&dWZ?9jJ~OIp$NA>z6sTG70UT?J9Vsy$V~xZd0YC+TY02WRYr0@KOcoD z^p&5P4nr(7_%c%A7uRZng<88Q8haW^kjRKy1)e=Mi@J#i<<*<$1=LW12(^85p6j%G zKhr<0vaXb~PWic}O|{vjR^O6ov>Mo`>3`)+f|>XIg2j3AYZckknNrOZ_McN3SHVGj z)P;@m#!sT8jtV%3p?ExEQ+wC#9irlJsAl^im5QfUI%{ zwet3M+wIkACgkE$#r+#$4>I`7Elfp_p{r=-KZ$4-% zW&;v&8w?#D%rNLU4>5c;bwuvZd@2U#P8slLZ&!iJIBb<%$1BR2cO`yG2IM6oFl?@et5uA(|SI39eruU4t=2D)FR|=h3ge zgYV~#FK{IMD1gpU@Tf1SzJ1K~yhv0{+yz;0Y69p7lnJ1ZDa_2#jqTZ18j%kzS^lr# zO&S|&UG$Yx-Q;(^@iy0sZdMzzavB00)nBh6;FWCxbiW<^HW!sXsT_B2#s;ORQF&P#pTmmq z;LL&nsc0Nh>9dHw2|xn?K08g=xO;a`S4FN`7e*x^8Ap&Wfm1KR>4h-NWhj_+P>LCv z)FV_#MuDIHi)lX1|MFiKIM(JG`qsHyBl^_q3YC<`2~VTavB0i4;R!Y`>ZlQB=!qmr?380TD9_VRQTW5rC%UY3Q z*aj<^}6TY z>VXN9ir!4*371c(!K797jTkd6l*U$VDsXSh;zBJ&q_hO+HAG&W73SV?Eo{|t_dY9J zp)C|bA2}CMh9vG|Dxo3J$G89uJzt~@ll$udq1q8t1P91mZbK{_fmD3BIfBwsDG2WP zqQTQp5`6`-M!uYuC<2}?Ig)pX2THh{uFyKME%WBfJ0%E3LY%E5hPy$iiNhtCy6R3f zZKr`=0xedYabO~2%fyyBqEIwD1;BZhWe6YbX5jtCuyxt5qBcwY%P)WbLoRd5HIykT z7Nlu?)0CCp%#P>$JZjl-MAm=%^K(3*P|fObgeIB>+VOMh6xzC`z}nmZr&8V%j6?G2 zzwi}KMa#_1LcNYG9LG!jr9D)OWP^Z4*z9*|U{_s!V;vzO2gc?W`mFz59&aSL2!jUM`IAMTiF6oY4O_@G zGwNAR#VXY7RQAbdE~l&N6>0}giG2XFjvemhdc`@=k*QKcK0kGO72$nZtM zbi~}X9;sX{{BPp3V&d~8I^$8eh?2wBJ3H`^ll6`iXIkjl>a>hefGXXmrt7exNwpvh z4SMdoW2AvEKg2%y{fprCtU5$dDTyIlPv8B?`Oz>$$8ISIL0_8t@{ogpz6!2x&Hs|n3L)(=1 zzr%;UxOL+g)bai3R2j1Q(wqGUdrXTf*Vz6OQn;t zwlhvZ>$h&f%C#F%#P6vp776*y(kD-XjbmQEeFI{`;tFw(O?ol7eaxH|HM;~#ECW|F zpM|yXarjs3Vc2Nkd9H0U?`Zk`+p}=zGR*!5G2bEBW8VfW!;VEfxLR8j7>?o7TLlIe zkr|gU@4G&Ix6x&tq4p=byzjM{LCQy$?>QrbS{0`#3SRB{8{3hwGVkB9VHM5P396b% zk?oGd$~NVdTXm^aGYK$lxckw^uyXw-r;k!eR^B98#*zuB;f!&&Rz|B@4UWyYaN$G< z7N_;yhA>^vLmY4ZC0x)quRV{i7jZ$~w{jAfGkE@0++G?^oot{PJ_HL{1a)NOTRHTp zyE0(6g0DLkSqu@xg-mTDWrM29k@RfW}ZULnc~D|khabZ(`dy+O_dlenc1tQ zss!>tqoq5v9z?MF9mQg}ix{%xOF0^;F*v;Bbm9R(Q#NaJklk#ENzZ{5Q@_I}$R!7-g^Ehv&2KCnwYt4+G4loiMC>bbli7s1pOwYV;*D@Dk>HI2B%3D zP7Ps1k{i2tlzZ+uJRhivbe3ycOjf!R8B{h*NF*%Cq@Wpra4R!t<+!ML_KvmwgT~LjykLF#t+%Y#Uw?h# zTOUFufIdJ7%s~x(*>Oy~-yPi-Tmf#VqA|JkO<1{oAMRhj4~4CrHgXe)6DATfCm|ym zfjQ-2pPvfBb8`_mH5-Ac#NjjD6mIfZLV@jK0hWt3IGu<<41M6-IV~6;`RP`X5e(ec z{2VlJqWSKJ*C2xc_?h`IWFn8r=p%Z+=f3ZuD1=VF1lrUwh+g_}P!rQ&EM1WO;Q!zc z!K>Av@Xjr0)D0+=C=f}&@gy9|{>NGWKxX#C0JLEkbDwo!jIs3eogWm;4^tT!W?Nmi z5tLPBMNx%~ZM1~dJXpH;DM}GRt58G6(*!KNT>-A!=BXA0xw$eaFpJx4F}rvy3a?&> zf~xcx1A)2rEQ2|yvuFvZbC)->Ug7!|k*EaS)GYb$JtWMt2*gEr=KK#~amj)UXAStq z_o{H?wh8%)$JO)Jf^ZovDeF&UsUJLdaBQ&YeRFvoUijRnVCl?p1RHH2sN=V

^;z z&#wPtuh{t3?DW*1o=pSor3e!lC=)>MA+1I$h=0+hWvi;@&w9dto*E7eY7|7;DV1`i zDE6Jr9ciBSTg_B_Zi3Kic}n*;S$0!l4VF?m9M6U!ONCWJA*ulh;O_Q6KMaYXKc0Go zSIQ1Fn=WiCKGan5(}!58u=-STYuB#U4W51Pqmn`_B7)nXz&!%vW9?6HBsf*1OGG?a-^nu&#?i7xld*y3ck095 zwF_aeKQ$iZ8V;-5Ieh-AaAHn}bV3d8)oz2LXEKamQdVu8i^tT;n`m*Xps%|Mj!C9; z2SPOG;QE$jatdpDiu$>SaqSso?KOzSa&YE^!T$7*Z%`e07b*>(*?QHIQsbA8NzkwQQ2&Y3uvs~@mDuWAAR&@z1ckDPa3-PmkFTvkXEA= z%W)OqJ35-Cp2z$3SBEJYLuU3{A76)!`x~%{OAC~g50h-W2<%5b@eD3@S^oQvP=&L=~r3aBJ zVfoa20vW;&-@C#kB2S{vFpEIGlzNQ5^FTPz%?KkKe}P$eJZn9qZ;c%G_n@PtP} zio}L)e*bN>beiz)JMTcPUc=*gkNaOIBO!POkHvBoE~=rmqJa)PxP7mWa2sOa2cye@ z!CdUy&Is!a{dvFr_V|31Z4CUZ+t2WTpF0%-3l;nS>Cf(Q5B2j)#~_5znN)X6$UeB9 z1VUqa3N2$Me0cc-IER$uwM#L`q5`U_y$+0`^``Li6uQ`E&>FV|%hzw9zq`owC-zHf zdYX&WJojUtlRV z6dU)~*k?{)PIcK^%$)q@MO&t%xk2D(8Z}*F=FcxgU?yQOm`74+baADTLE>UW!OO3J zZ`CERAA*o_jF1P%5wNJy$=xEF_|SiRV=c$|=^B~;5cp!$QLv&E zcombYTv1AS7=8Ry(JdZ&Jf?OfhUW>HxITZD{ox@tqwDfL`pdQH<6!z4x;%2Qv9XTk z^fKJLdk^Xe;J0tx=7{3kw{IgWu_V|d-Ke6Hvt0vNE(@5CBfy6T1@sJf|0v}#Dh&g- zH?)jtZa>I6qilB+vpb8w`!@JvI;k-bo?SF>ZV<4Az)Ff^MJW7S8u%d8Dzv%K7HR%qaklz&sM_$9f6SQ^=SNC~j?VlO+Ok%4q2(&3c_p@YGc?91Fqx zDYR($4SYUQ=!&YNUTng%7b9@|n1SiUT10Ej8-I2ke{D?~y7ZR`pm&pQjaG(W<`ncsK646y z>tyDRFBv%jdfk=GoFt8`mH^|krxKhq8bfd=Fjuq3Kp?vm;RN_LK6Lfc;Q>0Oq2ZH3 zk?2`eAl55oDAsMbwYJ5>ou5i`uDhX!cw(Ul+@_D_HPlMBYbJvo7r4M5&m}a783gEI zP#=e-oyHf(^Ocx_2>Qhp^pnS5{wkZ@m9Q+@M@+n0D8Sar3jF9t@56mGuYdPD-+}yg z9*Q`Lw$gxFDSA{Gr;3wVt|k!B6;xD^HHG^e++l$EIR5H>+Y#MA9%&n`KM%;h57o6W zGLXXPzVtyBfI|RtlIftN>^TH<%1i&|hmtAN^^YMto{A?y3+enE`auwF$!W5SXmw)^ z!uZ_1dNB$MQv~Q*|1l7=SJK=ujanVk^U#f%w}kxa7Ah2Lx9)Id$hnhe=~EnA8og~~ zIk4f`OA)SZzp`v{W0%#u%VR8}Ip3kCE=18$QPBkiK6QY52Qf9lJN&!E` zXVGc=4vwHPY3R~lCV<`{%fI`^i>j}ryhalr7e9uY;eR}AIoFTh{gBg4Zhd&O9nEeB zK%PevI~9&;1ZMUb>b;E5*jJy=a>chqROiTRVv{14!6l0ixeZn&2eI@LXbAAO-5}Hf zznX``5CSUlcfWo%0Zkm+50E0% za!6qPpu#XltjHK+5r?pi1Fs+a_Qf+1uF4jRC{RLRynMGwmD6CeSb##MvTK^ACP;zn z?S(U8?%)2oOHpLz0{V|bu%cc=CQ++45YRW;sc$Wzare z=gPP<;RvG0_OD7DL49fo^u=d5N?pbG#LQb_Rad#f-P-CZPmiGvb?UO2#Q_JO9sqgxHLjx)TsiA`0L>E}o_Hfzv42sq|2AkN) z)IN;RJVg7jZI{jLQ~;_|LXimix8va81Kuha#p!dX+)_R~0lN{3%b+@6&KrR{ALizC z-hL{!TP~Jz)k*aTtGG{~YI0JjZv_dN-Q(%Rp7zZ{$R+&wHu&z8rzq~_%a;{=zK>uP ztH&!7Ku5{_?*ILQuX?jiJwJ_i9V(RmZ^&;3&p6D?(F}d%2eL^4S5)(53D+HD<~w%a zL&vY?&~!^B*njSYDfT(1VLv(f$Z1@3j<3G|A#CNg;alJQ7DuZ8@SS&f8}v6x zqftl3J@~mNreGLGFv(bGa(7S(tHZ{zFcc{wIV63Xy*DuAXFc~n!ghxo!`N4+D|;S( z-94{k?!WK*QMb`6R&12*jIpv9vY`wWfjKp2@N(%?1R7{5E7!?d=5QoA1-sEI3qiq{ zg{eN%HdlYc@0A67gMX_Fcu%9!(6kYY(Z7wr&AIK(-Oi3wayCZ9Ar&VpIr_d8_Mvaw zxrgBF!Vb+vfL5*WDomwH=n|m)$YZ1QPLiMhg()_@gDBv*J-D;sa)YTV&VSSR`>2kL zUC2oO{5qxD72wZ)?@u5*n}rv@@bXYh9rrZtQ>ksw{&@PzZy6ckQUvdNFp;)Q03E1t zkgW@$M$pn_2o@Nsq$^3Qc#LIsx^!g!asqPO+chK-{%Oo`RfvaGX1i?GMt}k;aH41o zKBPt44cYJ5rZTK(!WVkb_yB){$_E^lh+yW92c|m@AAZvj444i#a`D-`o(O!&qyQ+2 zIM94O#Hct$PC;ddz+FwwFraJcx!qq-fg3zG7M>ddZ(`$hd|h8(hjB%8)Yok(Gq&q< zp$xy(7VeWG6ZZT_g_t=>k`(6PZ_^T7$DIKkKT0ACCP42W0LQi_kVRw+$*O^B!Iz=+ zT3ZNn$Zc3_=}cZ@s|9=y1OZnXX4;XqAMe z^019sWF)2@^v#&^g&V~wYl2_<a zie9Jay&%nu0@yzM-~+gS?>_wS-FM;Ety{b}`+eaD5b~W{X#HrQBGqbV`?JqP;YDOl zKXEDyvoUov_Bf>PT#U1gLEr8Fcog5cfc_<3hp{FM_)XU$GQ(_l|7XKok6sLY81_BP zF+X4#8Qf5&UG(j+#z1W)XwgpbYs++AFIVusMy1!Sav9meRtXw~0+g25+N+175zx>& z^~zuT3lNG%;YS}|=5)^Qe()|c^a}dcsUQyJy8pyy;&Aa)7#;``7C~n=v`XH&-GuLd zzYO=cT)3Zer7}zbw=u!)#wiL~4OR<<4VYS*fu+;O;DyhBdf0|8SA1Xm15Y(9O^?(a zU;WXszxWxd|eJr{J}^QkPuvh^&BP<}fuHnJ(YIxe@7bs?ckHgjNm##rXwUT+4kbimOL z-u?mH2uDi97{58}<7sb?ZemXsrNMc@4pP#{yiSU$8m44bmwLDHy-Gb8ykL&udp>9k z!_OY|aqwM!6=bJ>@xU9Q*&M2|AYT3B!1>^nD7agqx`r$H2LVQ zH{(-becE5Ud;-kM2~-&W1H7xhG|ak`mPQLjvv&r-RUKK=_;x)=gTf_a2wW8S;<*%@ zn~Oj)s&Noprxejg_TFj@wsF1NMHkL5&B6I&b5KF>YF4Xzertq7aN#qr@=ZUrI1gTN z1Kjm%;3M$)W(}SM37vhJgV>@k{Uissg-*W6%83%B=aAgJbC=ENfBZ*(1lxEXzW(*E zGk}*%hhvSP#xvY8ieeEcdYH`jK@IKwLizd`yl%h##ROa;-({Bxnz9nKsgrQ45yd42 z%lGd=VP^;a7bo+O)XDfP@a_ACRsmYU(> zIaIKwiEe|2C4J%K2fxdOU+M^q_n}xSGnjWRg*k+DvhkKLoY*r20KT7*?-z@DLsQf- zPJ$**QbyR|%6e*iim#;-P2rLOHM0b;)#P9!3w@WCuR$Hnj{;|$sc3H#;$f%zjkUSM zVCG}3e8~6eIBfVRQ<@RRX5xI*v>WIyvSghIH&{H`a+R36kDsTLNzm|F(-adL)x9Ku ztdDdroRa-`@Lv;0>-?JBA`C(ItH$IUO z@Sil3yI6bo-Ee60-kf5UUJ%0nMVwN8Nf}~RE$$TI{*61_{&e;B$^(s7$Y)MMcM*a4 zVnl_P7NhXei8yMxIu~nE(LXH0acWA=za?g!KoEX0QHMLZ8tgQ8pirrz->C>MoL+=u z)6-BwpL)xDMqqL0gO4DVN^!0C2;T6ilP`gryMv1_Bj25)RT+^OxSE`X9P;*cZ&LlRT8_K7*TYZ{`0F<4Y4W&9j zu8N9Q6tC;_B4`NWu^0X#g8DRsFZ?(+e$fcvzxhqr$$ty*Dgwm?-^edRR9NtZlR;YD zFwA^d>FT>3as9&_OXusj>-Ty;&N}0Q`KZStI{)-XTeshDM;QnHW^<UgA1jm))&@x4hU0PDf7uXcP@C>@Y6b-)kLYfOkMZ%p5 zso#4L+-DsXT-C$HfpgDjaQch^vG0}9uWrIecko%N`LI=&Wnzs4k`~-tx}%{B)ql^e zZ@~+neF?&`2r35siaLo`(AxHj>NNkcS2pcX_EZ`DbeVVG{ka?HSe*d+(=NH+{JT-4 zSI>B^`67b(&jU387$D@|p*Dc|^&G6-UPUuiIVk5UedUyz<^-i&$zPsDpAj*00`p^2 zVbpMuol~Qb82X3NR}9p`v*o)bc1M0HWT3MN8$O-Eo7zUUj>~i^25~g86T_p*P38P< zK^gL=Z``{N$t*HMT}Qtbl{h_xpng}H-l+)9QDN$2HbX}1YGLqjxpDb2Gwz!=Z*rlR zwY4?&jgx78eSM8Ta}J=Cw9MvCz`k27oZ3UW%+TpM?+xY@wM$b7Wg<{y|Ea|pm`cUr z+>gBi^Ya-Sk$70+$(L>UZLnS#Bjj&&w zvS%o_yk4nx+Y~;3CA6wJVCef}e*8Yij6{VixZ`snW83k1Z=vaY6OJ8^pif*ndDa1eis@$ ztLMu0Ix=;0>D8aF!zWBWQGo6>t5MZ3F5uMuIT*49Dgk;CHP;*g`kmFb`P&IaSob!t*Fhh}zS<^<-EFq)gwv!JBr5Y#i=L2Z9y0@8oyf~6Ih#b#y-a6v7beCeHl zP7mZJ0y=eZBeqUCq@kHP@M{GQdhwm+kpXlHz@dgIt{O%Ybp$^C_+w_~|N0OAh*QmO z-Mk5hDXsHIwb|)!V&x;H#Q+t`QBWz9g>yc4VF}J1Ux0I8{27>DI1Z5$&$k2nNLgs& zwb-fbz?Cak+JJrw0i6_-Idw|r`H#cc4hnw#e6Pc9;xNW?m|#A}F^O((9y6GWgI=31 zV<7NNB52;-sK9Ej3g_b)h=syIAsH8PtE=2_g^R`57Mi!4OceHSm&QhbP9}3h?_|e* zkGO%>9|_=&Za`&XNvU>Fm#5bP96#>E(vl9jEgRwnS`*NpZXyw)GO<*ACW@bh(Hly& z-_3fH$F_xlPAR){OA7-5otQfQ`-rw2H>e207Y4b}orPuA-S8{l)1S z^c5p3NB^;J#9;ZxEig?RftXC_=#Rw*j=Gm=y20%VHFQu>pJPSU_;d2rre~(XOQ+aG zMl7?moo@}0Yceliy#`Z@i#)dI)Jf1Xi{LDOK!xSer2qH><*fCapcFRY&Hv9ofu<6H z?|<)mtgNi9uHm^DKPa{3`z8~*=X%`!ku4`}M!s9|s+Y7BtGT$&Rl1&^(P0KB#nVa2 z&M7nD%#VKtrY?RKk|!?Vwag+|-{mTLAHM%Smz1RjFReUy0`YBpZMh4UixyYpYuYlH zj#!i2Z@0m~aMEQmfAUQ2BLu+>JBEGl4-!i-y3+6vj%UPmqd5N%?uA1ZuIoSvVqg(S zq6LqXY8OG=Art#nj;&OrjC%HNTnar4wtrdQ~M>(nJ2To z!gCod)5u>!$kOlQT$YFDUyMVwiWbjC87egoZmqjO2_!jmSE9QeEnmpgss1}Ig{>W^ zm20qYVu{Pd&L3ZdL4wcvFQMgiTPa;GtF;>x9QSAN36oC@pd(K_?g?L`)<*a`a31p! zteeP=3Dl{B8W&UuK!i-~6a+_wky(p;qnCE3 zGPY5?elN_0;Y3P-SLP7l$;YP($ece5(dS+Uk(lFX{QS->D4-(s_Sol`Dv0T^n6e=0J1<$zZ7EBno9S-#X+`I&LyPE z0#>Nsvy$7`mpRiZF3wv%f^of3XKJ?c!QYRs55_@c$jWhi3Y%V^WSe-b6q6(?4eu5HfoH9;=a()JiY=&1mc~|E#9sdG+C%2!=rr5 z8Z|

T6VRfpRdpBbqE?!rQ{vMy=MhfC>RfetiR~=zBi(+_PwcPe260hccy{>JB_^ zq2f1m0GEzmga$J7aR8kd1*gIUQM<&(TRF5|0HVG($gD27;vKQ%3)2Q9@$b(s>f9~v zSV~0z7m%WcHM-!Iuu5PS&ENSLw(2hY=67$xa=r>H%PU+Nuoz?;v=j;6L!c&-lBVJH zuQg@Cp&zb?xa98_PYzLg`=CKmz0A3zvd(_{8zJDVYXO;Ix3T}XT}{4Yu0N`D-G)DK zlMk5MAK1o0#~|OgY8_C2^qGtb-}?~fo3aOU6o`r-eJqm!AD7!`BzYEW%BkcdPfB2=~jdX`iwT3#q75U70m2<$#m<{cy$remY|KFcL$ zhZBt#N{h3RtWaJ%ZBs`}V{&Q=pH~5@PfVZYB%KF9sch8>`TXTR=wF&wDK06lN*88J z5uyM&dY))L9;PeX9`V%~PaLhRpNB0^EugQz^*@|K!%x`Sy1L-H7V^N1p{qa?}Q@w%U z5k;R=2q*a}bTbIk4Lc}stMB&#OWoYqf+A|*WpfR+TL%`xaAf4ASPjj2{d39NN)zXt z2Z3!IAm{|&dk_4!n-G{rae^XK`ZHM_jwe)jb>4tQ1a4yCluJvDJQjk15-Hq*a3cqb zSz#-|Frms?VCJ-gX#GE3QDG_~;HS>_SfLlI9v}~_GD1)KUXQ_ntGFG8AAB5n48HRR z*5CJjq_EUOvLd8nDp30N>#roBRCVFoKPqvvl=Yo$P5~oGRMG0EBa60cRj|rVV4O#G zf0A5<5jZ{<%w=Nm5nR9jF<9sb*Q{6APtS9iCnM?CZ{3E%#s-{x?h<6@XA$IILY~va zeZLFoR1<#sXR@%dX@UEvB~A@p%X^$PMCG&R(DKPG<8dw^hW_o}{|34!WAOSf{3QD5 z(b5*~{qQ3F`gOKKG@Jihw3N=R|K9)k%X-M!oc^g_y9!UaJhgxx(R9W13CJClRJEX} z|3Kl&VYNC(hH^x^znfp~1np4iBbqx&i6t{`ETlZpd5lcJ1V}YBBPG!M8sUZq50~<^ z@~s`S$$-vqY9+MqTTv&n9Cv1 ziXxmQzmBx;4rHu5s9-opjP6d@_fsk4x}&F_O0LGj3bJ007Yi3sG6~2vjtHib(=M1u zK3p!2MU7P=vbjo|oezHIEZby2SGfU8tCVukMiniO6tOOwv9y9n!V>iHZ8U~1uBgJL zWhvH#)*_vm0_EDeGr!`TTyG%rS7bTb0WFPNbG=XP(mhXjDnuHNqQfUZp1Q|+=WAa} zIVmmT-g@g5-#5|W;{C?3VE+D}{}4*~B3yarviu-ugSu_WhAZSd$7ck>c*B3`bR1@4 z8a#V4$!1(`e@Z1q8x^iuT(dm*;YtmDxQb?QWat#h{@lVeq#_|G<#M}Si>PfNK4epi z3vlY$OKh&9_t&o7gw4$y-n=pxFA|iDrMz`^0g%}_=vN#@|5yZ<@4SBnwu==wH)Svb z{VOjH_BTB;Q8hl+zqNjequby6(ffN$=;R+KM(cIBH-_4*B5UM7KO2G&o}<5dDatW;FO-Th`vBR*EKXkk_0Poc zUO|6gOn-2HWBAU8X6T&}@dH@=P`>kiv&J~S^HGj{z;8vj&quh+EhqfPOLp`v~6s znTXm>kvcjeXOV0?1SU6Zu({9+H=Jp)@Bw95NeG|`u<1C-FP$(n4s1J*rgduDm&JSBg7>gMA z!6+*qjy&#jO710!fT!}U4bu;vF&WTH<*4cV*{sS%Y5Fqr2Q(N`N~r-$np5Mr%`+~| zT8+)^okGtz&2=37iyCDdXJ^$wrtT;3`LH1ra=7r!^ppljQ=r;(Wj;JvIenSc9u7{V zZQ2~DOtnD_^wX!ZY3L{1$VE{uqK#tPub0cZu7~`0-qGQeS6qBPpSo&tPamM~Tsx!q z>RB|+{D(NL57i2Fb9Dm>+Xc9P^$w>=kdVozf;RSsOAK9_*Qu(}vA723vIbmOh{-mn z@eEf&)6RX4bHAxto6@L)YF~$E=OS=A8-j1$uE5T=33qaWE4zJaX&OSBD%+&`64a<| zY8ko~Lc`Bxe$jgyW3Rt&ouQa{k9E6#KF&1>)=4KdAjn&sF=R@mD?2>WE60)q%CG2j8TPaq zbbdiw4Z)eE&j6XxH<#BK$T#lXdq62?fXC(Dm8%>q_xx)=&gpcjK!3VkfvMSRI4=rr z(fYyVCKqce*YUZ*c{is6m!CZ@WFaRClB1gM?|x`_#FDbqlSD<7%I#} zH3W4P7UBvd1Cv}|;qUzeO^gw%fPO*;nM@d!JcWzN3=$PV+z(nsl7(ljDou$#n{3CY zo+BN`V`trCrm8(EIfycK6pm-4+lVYiKG&$Gxk^!jyKp2ej51XSHfDiUq6yqhxZ)`(6oj{9b{|Hx{J7;j!*M!>)i}m;F=^d)TGXeA?D~RS< zPcdHbYt1+eSzDxmzR+^949mCfbHf$SktIVGb)e>w}Y`9-A_(p$qX@+w* z9rU%zA}KBxiYeu`;q(j7Ll^=7<>xQ3_WX^?I-91q3RMR4a+3mDa2?ZyID*_1`tx5{ zh_GM3{h%H}Ij7_y&XKM<_igUhva~fzB}3@eKug1q9glE8+fSSbF%wURQEg z#zhiuZlKLQ2XoUI@Wbv2vJnfX|Zh|bW}QsTTxZbN>IhRihxezW2N_2+hw78aSmZUlN|1^(*D7SyqUl7vU+BCmzuKx8Bn3YikLsw338+ zBPv|?b3*uMkP-I`gyYIyL06yEJ1g99#dp27cA2+*j%Ftz%k>np-eV~P&Mib?3fVT7 zW=$_}m#rohov}Pvy?KiPoeI1d$lkM4DZKAz@ut=xRM-NgUWN;^5%j5RaI@3|BTSPojHas}kgO=kV`Cy#Seg|infqQYUr?8*(zb72Ho`pGl`JNwIJ&OdMG z5g(*aDQLolQwv#$)O>F7I!H)qYx&aYcG{_#kVh*+uBJd34&}Dih$y&#?1O3{)XQSmo`qn{>D?o)Sm)| zepd^H5*b9-q-XC$(Ju2@yl7wQH{p|J*F--Inc44re3OIXcB_s71A6QBG!Sg&A_(Z{ zn?8qra~;82(U6&^=Rw4?P$^asU`+({+YIQnQW;G^X~@ju_X+Z`XCaI?u;E(>=nh!6 z4%g9N-#|p)s5TIUHJHvO+0WzzRmaE-PfWdtOg%k4#eLDwUcAUv*KB`Xs;us=TVa2t zvZE|YWefDChk%YgG*n$SE5Kk*F$D{8jT_ti1!Ur6UcZo4`234~DS_fJ*xsn?2We|( z7N#JIfd1AHs}P{`=7qxUkph}0cOoim*K|muUJ&6kaPTm0(=j7#0N*|`qY{1I=G%= zasH%Iv+3C^&XER0koXJ+bRYSiP|$LKginh?F-0tW0_aCYRtwi-deJ!NIo7A}O8p#O z{7bzi7THeIW53JoD>q?#bqnmK75I33E^1%}6^jT%sJOvYOovaMj6)iMhI*P)z9dcV zX061@>8m&HbJ`UI(dRW}=oT{TTR4dH%oGE%nqC4eF$1xUTM#lE@c9!qG*PK|XT1y- znxvLdK_DM}5`E_6Pj`Y&VYCqQ53O&&GZ&77Z<`!Jzh9mNAn%kA9_v?*8Ti1f@Zz+_ z;5`?W9nR=H%*9k>=n6-zccxj59&mMVQ~UnU&PD4GACY`g?k{)HLzchOP~hE70q3$f zHKt(bF^K(dhCLq9-P}IZxg2!vM%l(F>-5{kxR&D1l@8O?F2=A$929U5<9h7*ZNK;u z0^3>qMH+v$2<5y9jmlkEzjK!(+Fhrk!3!#|u}lU^P7~dVn^3WuP@$d@Xidx+6^Np> zQi*7=oZA4Qxp4lhvbV&n*qzIkPEZ893abd{^|}YwS6$9s-)#7tHauteTpE_Lem3u~ zLuIE7(O8s8SrmbNKMCkK(pM2DW)!pfHP^N-hqA{~x4!l@|LjlxWC@-EdEx=xY6>*U zHfKTjXYmrgHfW;aE^6q@SwmAhnQVxyw~EKqUAa)G263l^M*dm_j!%UlY;>e`kYa%5 zCJ&8DWn|Hm^2Q${0CNdM1Z1jhOo4OpsVPorqYgx&>NabcC$nKT`+w{9HY*qf3g-;# zFh%`}TV29}S1K8+luB^=1QBdDiL z8&m~wv?-i?iQLlFw!p&ceIKn7>G7)Ijwer+zBiF0B{UOG;X>MH7V4FI2b79%dok; z$-xyg(UuUz3*@J9eD-Z;QEN;gfWLMw1;?kuu!Mka=(3zAMU~rlXMOA17X0w~D)hI;EHz~nLrdurNQ$6txDI` zL?w_+4wjE*MYR6Byr6RAZd-}zT)OYR|2R88m#1@ZiPwJH0)S!s^n3T?54YX@pLIL- zUe_0TnA!!5c29KM#=h@GtBA}H$J0I!LtdYrV-Q__+i$y_>jI2+j-kss{2RJ6(TwD0 z@eEvmTG@xSTX$gt&Ez|1F|?YEJ%01#;ykFa2wI=+!giyCkGuuXoYdfRFOaF;hg#i+ za=ngjrwUv;r@)2N27LNbgiY>kmcHlSrGi_6E6E){6@vBqO-Mxr6sj_Z-UOM66xDe1 zY-Od&ocZ-Fm^(Jl0jd2gm(-vOzy7>$*LKwUYUuy+KYimSJO%Q^GW5C3MGdvADNR!} zZ^*XVWE!uaNt~kF3CvqUW_IfK(<<#sfp8RzH5J#Hnd==zT4YfMA995&o#FlCjo3i5Y~6P8230wzgxYcP zjg6lR-9XdR4(DLIUIx^oRx@UhP;r$|5ObVTtvY_e>lYlH7nHz zm^lf>`A~7Jokk5UnLdQjBu>p&mS%NW*^~jLO-d8S`+hnTgA7{b(uv-DQih+P%X7xy zAmCV7faL^pD@aSK5nL;>YI4`gBDydeP5E36$RY`tI$8z&S4vS;PD3%HVzvWO8qnsU$#O-LAlmumNx1_u%}r0ka9M z@2T7Ei}KsUM%+h_`};ic3HH? z1!N>sVtrH-azWq>^(vhjH2t77G0KT1CQpA;M=*;PH2tu?81yyo9ETmWIi++DdZnJ} ziXH+j6h@8K;3hAc;MG__(k z4zXqnE^T?J5`g}JaDVKTAL4lzhxD7rC8L1u5jhS5;ig5k;Bmep7EE>1xivKYuWP*2 zaW1Q)e;f^qK;2ELglxzV5O~m7=xr z77Ac48t`l+3bQc{trWqnIPQdZkO_0d$2W{%{%K1vi>$cuuT#ti*;3!s&eZKSkpN+D9*U!g27mxgU3J(0d zkEZhV?K=F?cb4H;b_QNNc^1sAJUEpagmHdTkp+L_+6U0UIqcM;4sitYU;K$A7q)5x zH@<|?t%eqJNF+wIE_NLI;)xKN{XO`~m*bGzcA)v41~c_-oL==Pn%B`gfG>cyFu3uf z>-@Yu^WwAYOHXHe&z-o+uaY|e>bYOhgwlNRr(c`j_|_ki6E_D>pgd84p8tctlWa5* zEt|s!B-YAR269?jmEg!|MCNuo(C8?7om{!ehzhC5Xg3|1!432o5g-wuTga?Uya@|v z5zr`KG8EzfIj^H48nqOpNcd{8h&P~z3_Jvi5rJ?bg?=R;ed{LITBeF{S+wt_j;NoR z#!OZ6w5cUfqABoI9mnmX>1&(8o3aTu*4L4dn{e~yO^yrTa}g+27S+jbqN`(+zU_y? z;t#$JVb#C@2QujtT2m}26b2WaVv9y#AtGi`FV9JMaXc>R*-h<9lW_p= zC|!%gGPie;NC-{Y5$Wp=htV}zEhF~Xpd!^SH_@f&n4oGd#BlzcpVk=AnT?Oop7?>| z==DC3IF5yy%p_uhtKL;jS%{0~^N^6GZGGuP$9bs05$~ytjCbj0NyF#wBJQ&Z#oJeK zA|n(PuuB3XPQ4 zeSSuwk&ZVPwM_k2S4vPuXHvdehck0iaAtl6YCDBJOnvL#J$|JEGI0ciGcUdXQ6mb` zL=r-=J8&}Yaf#Rp-mI^n?>rMZnwLqNI>yXA@rA#_AWf$9wbeDa{Lx2n<>Qax%9Shd z(T5*$BzQY+q0tDMM7Xe0^Woc@T>2hPcge{H9orjo{5?K5@EJLGDGF(PZnjoT9FqqH^sATfp`s-ck=Z|7^%H;p{2heXIb(&=e#DF+s^ z?i*J>M$oRn?K^iNzmtcR z5pX=K(g^I~F{8-m5P->y`sK56*sR*{_3IVb$QNLFy9h6yJpsqi=TzI+0LR>| zGDtv9RpmlaWapv*Q%VU!t_6{pzPD%g5fy9WCN%W~eCO+5W0v|`zw>+SBc?RGUP4V- zTE%n9=mWc1av;}G(7k|457%^u(WR3mJwg^w0g=z4g{HbQ++!p=%=sMcPUoQ3FyVed zg)0&2k*;$2+XIok$Hf%)Z)5-8cQlZ13x%TDRx={>aZq7@gmj z&VpO^F=T5Ce!H+`E1orqEJ42+&D9DnO@bQB~;Am#x|wel!8}!xV}* z-1y!9QyLlEf-1b9!B6@o0Lzl8K5X1ygL0wNW{BL#gahGZK>|`LQ`B1=?Wtx=CGa~^Ev zdBEKMFyv96%Llgc;CV>KRWz>~9KoJ1Y48l1+R0~bXnnRfirKyEy4|k_`RF6K@6412 zCr%ki&TMw!QN|2)%50+Pohp2Ue8GJ>Htuh5KZV(23*0!%2pPSG5=Dmpi{Lw(qFMQx zp@!pk-uj(1Imk}G{=a-8>b)OnKo8Ofgx4sg6(1JR@>KpghA-A^4 zb^bz4$HAj9dDQwZj5njlfUdYr(5(t6b72JZM_Cv2AVR?>0iavefsx)Mt%fBOKuAhf zrD;K~s=!KF-tx)&%uo9IJ# z(bnE@Mg;UxLHHos8RR=32Y|-89=+BdReFH=NW*w23>roQ!9%z=c7H4SZZ{cIn2|># z3KT0IoH=GdEUJt?wyyi`wr+3biv08uWa*hK0eT1tlZRGV54K9wg%am^1awbGKsRxI z*;wA-?r*gUGKWO0C!m8YT>ncrr(FT3{#{piNt~k7&1U+EY2b3CtCakWPwU4k*T3_; zaGZY^5%90!WO#DWI%{{A;qJBDuyS)5>gYeATtt%9hR?xpR1q$Yh<*%j#tZXNxO6-L zSp;8u5fYzo84tay%0WNrU=7gLWPA`pGl(I=fdAL zx%az-!vKhY-rMQ|=v)>Q6|t%x0WvJ3i zS$bqmSQzSf_LLlj!Jl{CPOoDY(6@x_o^ABnPPfndU60m&_kVR5*RY?G*6TN7ZxI&h<3y~%{OJVlv28IdMYC~)BC0-H~fpp4CnPqZo{uG zoB!~)zWqd0lRMJL(G)(V7Ea;iIE!yD4YN+IT!ZpXi3_*5&MvSJkefk~0m92D-VAYM zgDC`1?U2s`-6j;VoCquc1ngvrucO($fJ%m|YTzOe+W1Q@JBz-4DpEq-#==h!n3GW2 zUBa)UYHPMDq74%Ih0;-Yr;hA&+eGu2H+bD6CDbU#u^@tW$EkD@BH`hzJY@cBp+eI} zUpfMM)0VyM$C5!4{6r>l7$PW@O<`uP9)Vz8QZ8bsT*PBImq!Jg|0%Gv>B^=3G;v|E z2B)z#YmI?!L6A)SlJNZ{*ELg`;~m_5`-tR7n%wWa^;UTLxRES<@F!U?OL4TE=!4dw zsP;l`2ku?F!=2Px=HH?v^Asy+Zl`qaMbs>hr49Jhu{cbp42Xsvo{@r?I^Or6UW&r= z^AUJ|y$&VRCO=+YMbnVS4+sJNzxiAm(&)=4K!4)qW%OT(?K_ZFGVrC(zY44C8}R<+ z{^d~VyiojrG&@_cRddkw(17)Y5R_9?F;B=8u6`_R*Z?0f;QcVNj}7ma88q>|mhho) zAK-l$u&H1Jv#XI+iJlB@XWJOSVEtE9bJF9EgP<{ zQUfit)}n$;eb;7iiYH%sDQCld#0RQ5fAahp$j(kdKOyfR8h8~y7GGHX+JCD-!@aij z^MAb#M_7&|pc{#b(kzEH;cE&-9S$>bk!hWZ$507Yo4Tk4Y@EQH{%kGeKi5%>qw=ow z`Y?Nmx3)~dcC?TwovO-F6u23%G3vY;L-RYe6jdJLSRSfyk9G^qa3QWyKa7YD+a+ZO zP{~~CL+^1ZUhzaRPBN;5H5l2_!{@*c$^uj7g+0cE`h?yx6Pd_i2t7ioP7N;=X6#g< z&JW6Y(-iBlk|JGP^dH5zQ1(-&^>&abF2RN$(lztQ2azAi0a`bHIExnPR~6U%tEe^p za=+kH3V@^PY%6z`;hjJI9+>qeUp$9vwWII6i5Jn6>1i3H=$}TWypRpUxurNfYWY-9 zE|yritYPkRAlS*w6JycoDbzLXFU^JF&l@_tGsN#nc_EfcyUdQ917w6>*6uH@Pkc& z%SC`+c;4qm6UqUQ`ml<~9EyH9##qE5Y~#S|2fyv~op*lz$i{Jy^?03LjCYI+a?oQR z^ZDxcTMk5~ve7u5fBLgAs8w93f2{)bx)1j@eQu-_O?Y4+Nr>P^wpKPFx0b`_Pv5GI8KOK{JT#U~olktGaPMq0<+K6WZaOjZh4vi0sOb-X^7 zTlj$H_J=KFjA0ynJCgFi^Dsh_qHd<{!<3<25CfC%Ec1bDw#h%57Bt6ole_BuHc5QYVl-DOU4)fSO5MO*8d;>-8Tm3=spHH zQuHun=2WPyC493yO~vx@ywCLeJ^9K_(}o6u2(`>3AvmX|CN}#}eCgjr%uGggh@+!Z z4f>f+-648OGaROV{Lzk-#+P&?87>av9>n^nDIAwdK5jGG!4<#2^X5o)TMCDmE}OA)|C0_{YN)Lcw}2<+OwNR#5$uQt3Q&a z)g$FY_X@cvp5;sESNxLj{lDJt9-;y=MP%nYTX|T$z1lXL)Et?jMkQWNd_9FskAjt+ zKbhdV#3B9ZV8lmGJO}(*3FZ=u@c9=nzz;tH*xK%&y4fnSqS`itTE1#SvEjmIMZi=@ zgT;gnBkNvb!22=Q5kqccK5RiYUV(2KHVi8|9zSiqX*StX@%>f7QT|^(v%B44Wgv?j zY9sr$)#bZUwlmiC7_^O1qzl6nBUFTYXuk7NuE!u|KJ0cn|2Qa^k9uB2uXPU&=6=VA z^zn0_PO#PM>W2-epf9~xqf*~KY`Fr`hy@v3OayXMG-375GE_nrT~99-}&mTdr;mfw|kru zqiaxGN(6I?W+y8OnJzawT}G#)rt$D zhR>1zBxhOoFZS@{Olc>frV zm>dZ}zl`T`7L0j69F2+Q&QJ}vT$=#>J_p2cN&*Ep;OEqIrHm|{dh~`AYMNp|m?GR0 z!uxof=G| zmE!oZImqR<2Ld_;MJgR`hgDK$Wd5t1VD|5}%b3O36aNsOkF%{2*FT8W_%OkI>~nCK zV;J=Lz~B0CRG*KBzHab)BP?0Ki8CRH<{Y?l$6}^V9kgRAx?_a|bNUrocoix`jq?uI z4e0~u#MJo@&;EUUFsa4r1kk%l3RYBir?P~OjWa^{e-%&NbU!UKpW9)-c_CM5mv*&+ zPHNN^m9A?>7Z5>EKRFwLs4-#Yk3{gqQ$6}b@ixpD4lFG#!q!%9V109Xh;)#Vr!M|? zy9`i7rOf84jdVSSc(M;`a_)RP>Ncoy94eNJ*(lhVEPU{R0CT`9t#-04D@D0#fIVDldmLEoD8XEJ9SZenAPAWvRBa01X_I?;%Xc+nG6(*#i1IOsLHO{ zxnRjo2v$(O@t}m`(F#r$XccnwD5tRvBP}Zh`Oq7d44&Ptq3K=QgGL9FC+j3m9c2L84M-dEoJh&3x&{YOT#Q_#Z>`AG0WB@6*4rb3VkYY>lUoPR!%MqnzjO`GJ(6~u*{PWi#-Oi zpjKeoSce!|iE6q&P@y3qmjjvJo1V$Q{;g#d;^+(f%!%IX9A?1Qp_=W7WRBv1>mPUw z9qWu81b0vdeQ4`;X}+@ekB7MLA+~W4iw2B$f0AV{8rR^$i&2QL*ib3EkS`-nP^b&K z1_>6zo?y4u?JKt-5{tlvPd~>NvQVEa9kkZ}Dp`A!wQsM1BPcib+i*nWu>-o}TPY3H z*eL5z?s+TUyjA9p6fJ6Wl2Czt=Mh7NSXkv0wMm-VBNSP=0U~(rr=n2~_!=ZFX5LC+ zqcX4pFK-PmXw!J|u3bz)P*$2;Tt^wQaFFbFJ)k%P~?bP>vK z7{30E!3w;t>3qy}A-h3+u-=5(7)~^nDw)JMaUcg_d)?MM2;=Paew=NMxQ$VK=R<64 z@9U#l_fYozn0)8^*B_w)ORsJC``-7G5Snb~kB1Pbk(qDVAPk2~zEaf&ol)1F4%yc89uL7}XH@MPr+)mJnXnnxlY?Xg9R{q@fzUa8;s{k~B z)qRINq=SpdP&YLy&u3c}w@7UXnc1mUJ82~p5FFwbr78otGVz-~9@z&DiLeIQ7}d@n zKH|HzP_q&fm4Gt(Rchn37TrIlA#RDo>@XJg8W8nRvC(y2h7qcm*V#sweCcINj6TK@ zj`@*EH!vS@-6J96jOC$Rk5NqMeV(6D#&n?Z_bDNKkaIeO5FF@;He`a2#Bf1VyP*Mh zyd;I$54`EzsS`1#Tqp&8^&!Ob&=#qvtMB|?^qqJ9(Qps?Ly|{sCb)U?4~?%pJENN) z|1gaWl&G@t%^y65VaD%^16a2DZg+%r#37DjBzbV35d@3uoDRu#2dX7hva9m*2Bo3V_c&N$=(SP}t-^Jv z*BWSD(~#YFC*F8yQN*#=eAix8i}&+3XjOQO^2h-_YI<`XG>^02+=mzXU1(x8E>7y( z>p8f8{Vu;JX}Yp4YQrT0y`02)$J`=Vu%l!J%#m_>uR);IsZ^0mGMfww{ zQ)0kc!Gx`>hrq6&`$FCAwSGXh)U_hqkn8r{-(e~PW3yL(_w6X>qTe|kc?@uH_S^b= zWUGoe97W>L*!KY%ubNxoWAx zJ!|QeBHUY7wS@juD)UN3WTMDek~q<&qAH{j)Qw3uwZ|*_!LnHfQQLu&OY?B{)NvR_ z6fQEO0>!&ilalp{4Y`^NP1NFScZA8|FekMG$eFYUCz7L0YIOYMg0OIM*}-GKw(UW_ zafsnJ2Fq*Cr`RCU(u`t zfIbK3PMsKPGt{s|C8mlSApG7yK;N#}&~$w6nLg539uq_9T;)v0hZCvco7HezS+r76 zIb0iE6gv$9bRV|s2goB1*v{Ul_Tkp)`uQmP?Y7E6fwb4y25qNfoyXSH20F%a2*>eQ z!2B@Af7oC?#5UCc(9>BJW)^hFAfTsX0xBlrjRkEmr{Y)?6t{Z&J{K|@emvnQgpBFi zcdKD|4D!fK?y0TsrX9nW(S`CeI8A@i_j~7^lWCpu&3AGI?sZ;a?2?Y5O{AK}*$I(?o`@!R2ioT`MY_ z%PK?f_rZ;K?gz$~9>?BoliB($@Jtux=H}3sZgPG5K|+OQJl{jNg9(KOz~wD~6WQJJ z$9wMe15M5cC?eBuopILR|M|$<7|qlU{eC<47)D%o&^AZfMyK|4K;^IVb?kM=vm$iw zbq>Re@CR-;J8Q5%edV5oKleaGg_+{03y3Wt{6PZ$woMDl`7-Qm?LcmQ3o_GLZs5{G zP72}ws$y6FOxd~dXGw$oZ6jy`ha-;+(4)E+L3*C`6nN2h;kAB~X)ASr`qUP-3*0J| zgff?ipizW7oqP(0qk7rgfF(RJwI5}fjVfSk!(Su1Jrrc9;JKWaPRR|cRd4v9up=Z< zYa3#C<0q3DXf*0W0Xo&S7eW0bigsT`owjT~iOp&z@>pbYlk}B%O6BymI5PAGK3i&F zxoU8cG9Lk5aQs%I*5H)s3R;U3sYE|OkK*#0@ZAl+S^vsAx zjSl*4F<*e&mv6!r`p;d{ZddWyLO%zA`ZR(#b)s6zgxSnKn+@{?naD$w5zepZ!qkq{ zZ{Xi5%+AfS1t!0pAGn>6p`#C7dno470_bx4Fqxgf!?_p#ZL zWenyf4q+PyUO)Kl*bP|VkjBxu?pW*fV!UGC`vLpz_1j^`)NLCFv1qhDKCo3}c&mi0 z90zdfLKvoIG+5oL0rAGwEgxctE$KKicHEps>Cwv@&_Ga6XVMUkM*41-UCEBEE0IiM z`MZCVy=jKZufP8KBdd4$$N=5;C?nU^aFQG7w(7y;@~pThed@rz<{j!W|Ypj`WX&hEv=-3+zxOS?Vb0P?alO zT<-v2JdueUh8)HFX;jj|u_^-e5Mqc5?IvF?ckyg@06;u)xEyRN%WBXN(84Sn(^3>8 zq$G^QBRx|O9nkN*^-t4bHMZ#HZ_GfW-1oO+YNu9{JGmXW@!^fOslAFXO;56O0`$d* z!adGkekKk2gqlBk8H1hpHOa_-?n{3ODz!TNkNx$p0>hID}A5r@@K=Ag{G^K~5Q%6>;t;QWJImJa-U_}$kXWxnWK zZ~t~iln0o9$2Lw~46_^e>W}L9jQNl&y39B?5NKk!;xw7zs|_^0H(?!_I%S>AEzRNF z)YEQhQ_0jwcqwPM}DBTal zP^nXrJqk-bC`gSXUDj7T6LfsyLI~2WeDi^u={TVd9y3Myla-?NY>YmRKIJ#Zk;8Ij zJV|mGpnqu6sX+~Ca(<}i{{T7X{0EFKtz#c=&-{!LOK&lC8Vj>@FDMDiwA%*@S-Ncw z*SH07P7&UtFRlL28M?N!k@SUkN%7pj>Iys02VFXEEb z1qZ_&p9(|RP$83etYvdQ8FCOX@3QU}r!B}C7W`8fW_$RsAw#DI39jct)3lJC3;2`! z9(-m&f$8WF;}rwO*mcK!J{xxZeZNy&6XH7`!n7NMS6+SzwsPBW^XBdTo58_`xH*K+ z41KNSp|#3^FP>CTp}`4A3^<NfWL_7K5b z!05-(`S$_NY1gRsp;xAVMvv%k?MDrQY%hK)3eAQG`7H;kO&@Nr!%qZz49x`-_C~Q&}Oi5wjn)>5Kd6<%VoD1^hq)m|V=44K_Y$j4PMWwk)?50PoM zWGr)UuQ&Sy$4f!7*?0(&k>Q^6PG34VlA!Dl(}Qx;W5zycP)}yzlrAz3SdDNz9&#H8 z!ceiJP{5^b3q03{7_c#_LfDpvaF358N6IQO{C4;2KE2lAhAp^|;fyW73Wxk~neohJ!Og#YH7j|8wD8bha!YMXjKqeMb6uT)jhuQ2fR6OiA# za+^&XBoqi_bIo>H>NSOw#6XHpC0^A@Al&1TZY*hpOOYvD0pC*L^y$;^KeP8=!Lnp$ zdMNg-bmeP%d-n0CyH9(x1JD2lW@a$-R^sSVB6Y7QUP__R1F5(XlK60A7@>Q0^>QhO zLJyK&Bub=0v_ldc0vOYS2GD2#?a=0Uf42AKT^jxW%FNoeYgbj8s(sFB^!~f+)UK*r zD_3T&wSNEodwY9WSy@HU=~zQ&40xUvn8Wm}Crr;v(nOnies06L;wP=Q1{4T1sH7moINr%slG-==B()FfbAD zdzd~tK1V@=YltlB$~bNmk|@*syr^9v3y6hNQ7{jJ#vg~7$FT&&J@;|+F)BeIhOpMl zcivAtI&~pI%A|!HF?Hfq$R-{6UZ6%9YLum8_O|xPVkl6pRw0PvXLFgrF<Y(?%Lo zw?0|_1QJW`c|cC~r|3|{XDPQ34VET`viz8?eOH*3vy0S^vbDO=)ZB%8B#*_$kIB3Od%YO=!fVmS)DJ8G0okgR8BfdX?C0Qqjw`7K$}sw!G2*&p(meNr{NX&;89k3HK{3$IR#o6WxgMTfj52}|YkFbl zhT{ree*XMpm&183sR;-@4J9=Nh2PWDD3ulLmq}o(?$O*L!HZ0>?9wbJn+YAXJBR+AXIikC0UONRdORRogiA;$50!?e*X z)v#W)u|iDk^f+S@sDWb`8Wm0){VGy>j}nTBi-|4V)2p&ZI%jnRrNgk6u6t!w`PlnK z1*WRutF*eNgO!B7W9j)hPMZOJNM_Cz5^0Td(WFCVjiYLBhnhOk+WNqaEn)?Upm{Pk0X5|K1IC;od=JSna8lk9D48f z`=BoRY0g73^EmnJoR@AS1ZGbeNbXzM-n3AxI@l#4FU4Uj1{>I1h?G2?Kd>5xn-9c*A!Fz{4#X*7i=f)YG%Eju`D|gbR`_s&H)Ei@}I*4k>Oj{Anm+D zYWh@yOQZ_Sk0(yB+Mgf_69m_bG!pKfP86}F*Cn&^frADSYpJ>iw!--4s}+Y#?*geL z`J^+^$8hM_VW(7tOqm|b%l}h3H%TM9{!xe1r49;rdd*qg$WyasaPPs+Gu0W|S zP;V+o=*pqWR3ouO#JD$71JBGtQ4MTpXX!cF`0(~V47-eM;~r*n!1<|&9d^ElY|}Qi zli(hB(Ft@Pv3&}U|Zx^+isnT-UQ z*#pnPTF3s@F6z~K`#Z+81x0@hM$Hps5mZ#N-BYlP&Lip=REPe(0^s`8u{U$N=8EIy> zNXxo?>$b$x|M=riu(Q358`rO4Z*L#_dwaNZ?;a|Z3MmopUUYlijd;GeVDvuU(Ceb} z%Lu7w>^ewIqv7PS?<`?|cO8YD4V;~*U^d?f*GK1juiwJ7?^l2&LLZ|7kr@Oa6J{(N z@Rl9Z(5O3@oTI(Q;CLO21U^zA*q6?Jb~>(AZ^|aC_g2U?qvF)LQ+>O&9s6(7xGK*6 z%71H@ws@1fgJYy)Vdz2?IY+g)n%c8L_mrjMR?|YG)@X0mmZzEXC%%Ck(a!!i&OPVX z34Ojvkaj7WB@)u6FgBLQUWj5PLi%5oHgjvxA}cmrpc&ioL$021>KI~*D+Q9-Ne^kt z^@9W1^}wcg)+~!P8++BqgoVo%1JZVt zCcQ(8e~cE=4Bg;Uq?u1;bYkX;%n>}HW1uMRxlw3)j!l|`fp0C4+*jVlz556_r_0c} zPB{Co>cl8&%?hq>+L$0o`qiZ*k{ugwYyg?g?}PdfA^PY;d8dG9?5kMJT9}%ilBQm> zHMoWYN4h6;Lo#!I{c=^souZ0wJp-gg_cc4A$I^4$J$$(O+)KnDmymw?cgT!ANeuiP zF%{a-=w;f1_AG%9-v5voW)*+%z3<8Np10n5OOC~AHJ~*#d}%g`InsjW$F*o<2mxf# zsVnlmFte6)#zJ%RuDAHFA<^}`1bAL;@|)N_fTQbp*%}?LT&ScJ+;{5qKj)9Jaq1&cO ztK8ATY^qH%UvLTlI*PE!QWoA*kWjCR@XBTioYXx3^&!?yQ@Sb(?1Ulz*-MZW$<$oo zkG1vB8!2GS=%x%1l$M7OJ8V0J&-=`^4XWm&TMtqr=T~N0`lZ#}{K0R;6j>;5k)Xwl zoK4vLUaQqSUnBYbTXe-{%;GXJ$gzk~ljho}S5P8hVq<+>GVsmK{_Y(KY0v>RTxp0W zKtmUsk}$BE>u%xc zVEgHp9aDk%R!a|;amCNVrirB{Qp&2ab8LZNBYozpKmCtqHDT)Jy>|kSWwRkKm^)W) zpa^Gt&v2o=u-bxIaqjBgsdOP!;{ti%2iUqH~8ahIb36beYlL$*v^iq^sH3+kYmoGk# z%-KbJ|E-^4eRFV0S-y6Daea7`)7Q3YBn&k0a5n?XR53pmVsja039&Gd$U$Fx9ot)5 zxbw50;p)|^xOVj#KKb}#tSm1}2JWZf@%omqy%xjv)^Ud}?_YhQ;7Lpth63 zjng{*%A0ERdmKf3KaRHjK8NW-934X}v60#)(+bX9GGvS4eP6$a^6f%PxS4U1c86d@gJ?5Kl?2m_jlFzohxqcYOJ)86N*QpxYc3$;JTn>9@J^4WEfaWnm-3K zbYFw=wJ6s1I5%B(Me}KBz@cF_rWk#Yfda{pTaTX+;NJsR(g{wBXT`}>vTBq`xJ8IRB;wObJ_RBL5< zY^hX|<7<9%mrIiCEWb7S{BRXpAQY)+I(;cij#4K^^b$@+t$ju1d*v0$`T!piK|F$ zH)w;S%bli$Gm};^o6|9#F_2B37?6&IhLMhk^brd3fs4Hg&dr>|w~SR4b+a~SF|_|AQ5t&~zb>{e`i z_@IgB=5=B^B*f|BFobiE?>xly90e6|@bdW#&SL`q;Xj3G?=o^Ok7+v!wsy;~Xso}y zMRO~w;Ekt3%&$P6`nPo4cPG4UxFb6=IY^32G6zy7_u9C?2mKm7jpr5oel z|NDP0-5VU($Bf*!fUrPyZ3S2>2z>Wd(j+H4gr<>c-$PVW>(-n{5RWi?PJ8d;cn;*o zHC%W;1wGY}fLJ#l0*re$mvd9qxM&L(5xeo>XPB6o#LWCO0*6r9nrj}TKr~V=DbP}_ zrW48|%7Jj@LQ#U;^Sov4igh#7i-TpRo=K?4r*+SNenO9&hB3EGazgc=O9-4wsrW3! zb3V{g-5@#EptxYkM%f}J?+j+>kIM28rW>!Hghg6cYYX{o3i*6qMqu+MJ&05iTpYQh zK;Ghw3S?0U$pFL& zJu+RVW~9$~HhmdcWvY#~=R->mB37dWgBa1@Es`DY?+92!C{{u>s8fT+H0{F9l3AU> zZS<*U=?3Z0^5@CNYM|CIN%*N?XSX2T8l2L5|G@)k1-WwNiqys%^?IAxcNXtqsyAtr zRl3I&f&Getv5fNA>s}0}L63;}#kd8mosUhb*jcB0s6tw3IHcf#Vy7nG|oR)FqzS?FqJ&XJ%1cDh?$3494>PSqs7mX&q~W{_+=`5a2%Vs7&(r$ zzlPnywXGz^NeX;n&KP{YIR3f5AL3D`7MUhyo*|doEHU%Fg?Ze)b0?6YbFmhkv|ElN zAZG)vZ;|HE^6=98W$=a48iNMznw&4qsMy^IcO!U%e-H0xweWrqIVeGSEi zz@K}i|5yf&pR{mJ@zdBZPGd@*`L5K=wd_*+5VpANkt^c?G4KyR_y8Zg_dXunzc2mc z9GlSdHb`p%2`?>Gf)AC*(aX8h>m-0oW>n--2103Az1HfJph1Ui-^&8f`CFLwovrC} zDyLvRksyX{(mW+4GvUZ;k2T?5SITi=%eU8dppXE`&rjDin)3mvY(mrQOl5XmQ#g3+ z$z$mIfBO4lb+x7Is`KYab{QCo!M-2%lU7PqX>ymjp>$))Lw=jDw4^h)OLe3Uf%pzUc>0YnxwdlSos5V>>qk&dKI+sGsn#Uv( z<1)yN$HTxjYKF%&220I@x8EC|eI~W;+qZ7Xd4HdtKc_IRt*v2gbq$66eY(G`!13~W zaBCj8Cir`dM@IAG`~qaj-huZp4EgJN2pYAaSqvehhiSt`FwRR)6JsBr){rlnbW3g2 z$i>I&Z$@*G;usLES!)nu-y)5E3}X{x{ZA{LzeaYS2cmd?U0Ccm8!d9&Xf$-Kl_%9a zZ3^+{=?YH`I<{Wtz?!;b=CyK-%y6#xqGGxCn33U9^x|mJv^2S&_|A`wdTHIGWac6J zN|`038y3cOV(9rCX`YR644pI+j`(J}S0vxMJ|OQlaNHOTGxtA+ZEU;D@bv5$N&J&| zTMM>ENecxtNKR#<*M6l1gWk8xCJDjh>&>VG#}1#6sWP+?+I5hlzGq z6}3HfRyfv)q0f*Hz1HB!IAtJ1XEVP@PC%c2iN-=>nthF!`W!LygET*8-aIBYqx0YF zA7@5><+Ce@L&9GV-nHJ{gskb#zVvhyO}A&~{7)Z5xJZ5U_&X+zjF}IbTRd-dH!po+ zh8X&mC4(h*i|n=mW5I&&3&%4wYIV}&x1@$Xh@lhxb@IJ`>@+GrFi{$LF8WBgWo_@? zG?@X%IHfk|*z$f+R#r2cEti>l8hVBNpPZ&PNehJ$wC1N0$fop@yz}Fr2)A@3ATmMi ztp=P1YpJL3rQ9UmDV5M{4BqWs)HoMxg#<}#(Awa?cdBk_-HB8PrWRFmAF_`@o6xyz z4bw_RM$?8R-oUvl8FWUzs`pj|PK^ni3y#f+FTmMNh#E2UY#uK^_Z03uT$Kf82A;}e z=q#l1-^HqhhuaMlYDtvq4$>(#IO1L2JVi2X&WAV1oX);yef}l4;0kNQnp+ZeuUyCe z#w}^C=1A}x*RD&ZdGp4NKtZu{%uGCPrWz?CJ4Fq@x^Lk8EO35Kfr}NdNdGqnvFXz< zx?>_n&VGEUjjP1m6I0Z-ioJ)|qz1mTwT(|d{Zwk^_wV16@2e}Tp~u#Xq=rtypzxIW z2b(roZb)-%k`*iE79Qz+pP%xHuk>O703qZV)k?DLgpT^SI6m9SZNbU9F2<*K^2Y_d``(Ik!G!M>1q)W=F3+14V9ik`!% z#aZlzfbErImBB*pdaltkvdQURZs@3+D$@PZs}7O7iz=k~vT0qPe?};OFnYD@&p>GF(*hi*PiX7Ma@xR(5Sn<@{W9m#K5%7bP)4 zLdNTIOo^p$$?Bj+)_{i7dAzj&h&0(U(GNpVMr_I)f=+!R5c z7i=C@Pr{I5Q<6*^Y;sT0J0r$PTnWJuZD_-6$ly5IwAl0>NRA_%MlGpo*2wFCkH+NQ zXeNYWr)csjK^k>&uY~mnYi$jzMw&U}wr9Bji^@!0Ae(T5;Zi5K?Z;33%*|1?*BGYu z?qknnh^eQV_){%dOFbx9qLG=)ktJ1m^ZeWJ!`+kVlh-?doMD)$apqo7wanCy_drL zQ?DTN!mBi{^H6w99J$V>|D+o}be|aZK9A|+Po#x_$5bS9dck}7V~R_DzCRb}@zd61 zEQx$~f7>rLNEm72`Z8p+`wQp0ltDSKU8_f3%%UmAaeY0FhN&P^`)yUSvRz{b*CTEPGvlN=lhdDzIOU+UmFPs|410Ra7;y5A{6&+lIe=eq}pDwcwS~~ za%Y#6<_VZQnV6ZM;I@CUD5u%95Lm+w-^K+UBHK{Q1=iT9ImnOPkQISqPFcmOLa_z% zV+*jF;RJWScE_t2!3@1X*IsTq2e8RFJ|b@z3133Khb2GNkT*ZBC0(f5*s1ifNYHk| zWmsi^+t^w1k-q>nf0{JmG18C@wyj!imzZNo;dyj}fR;RwdvLo7Z_GVrCEIB;b9q0#;834h zoIOPMo99F>-H+wD8?GrbXo)z0@FDA*XlveJ(Z#d3i{|}c*t&>z< z-Yb)7qCz*oJ-+0n+f3@bIVhOQ>ln-E9>n4aLmw#(BO#B%2R-OBQMPoSw1ahAJT(P7 zGlSc=@3@G91Bj(y-gMb?$>EhhS>ZG|;BUR?S`3syNLj;7uP#ltmu5b&&5`ddi4Xae zr>99{O5vTKA&`7?u#9e|&3uE_R-W$1hYx{iE-*1`^dG~Jb0O{Q;jHx$PUjq)T3V7O z?I4E5<28(gTOE%!z4sp~xV@|3FTFX9d`3h1!gpPh^_g$bE}9~yxhQ?oY)-G#$gMyE zz%PIFhmwK+`0ckPlf3fjXR>epo9BvKXk~O2=(re=O>PhtM(PajFGi2pBBctw($rqsIE43J=r*s&kt?%ttNihZ1wjCJ!d%{JKW2o4|&OVm!Jiy|a zMe?Wj4UT)3)YyLv(R$0-zV=T{vq38sBauLdV(27=Xst#qMJsMrahx$5{TC8T(bzb1?_hik?&=i@La}o^q_$U^D%qWxR?bg;lQ0dDJ zTc$m7(H54hqefwfz8|7Aj7tv2Qw~`0?<^29@U&h@RR)^jjlX6(*d^m#COPUPp~IxI zZOv(rB`t}3E=i269LUf)5?gVc_VcQ8fD!#^C+Fa#G}6FNNro=6i?GP@P)8PK!z2b) zm*(?ot%}W!Eo|>>ySdqPzKx9y#3dh~XyBOrvbElrTQomQq?&E+lt^Q1$lum!47=Oz zn3$n&ZfqhBbv|neiEVp-aUmj3NAuuaZQBYMv%8PVzqK?=CFJLyBiV=;dis=`MweNF zNG;N90j9c(rd>v%Ttl%`gIcx8;$zD?;EIC7Kq<$yEywA1R04TOG7JStTA!TP&o6#j zZow88{DG0N@L`__#)(xgw(qyPJkuwNQfF{-$` zhqVW*sE|2K&Qx#mR!tY1ntkZGq$+*q4QG<3yFFOm_yWU^kNjkZx!aDAKnvgG%=I2B|&JfPUV^M3usxG&GA)`&Tig({Jd zn|GL?DOmu8H{cedusQhQEe&5jO+L`Y&cPrWi5^XQ#2Q>Yw}kJ`U&0^$$xmd3wL!#! zhr(b$Embnejr}IJ=y~rw{r8brSir*N%k67sSkw1@{71Ov6@R%-erRUiL7+Qf$!DHH zOxU5e+?JEA# zpZ_h)%`af;TmPjSmykY~6l~Qfm8-aU^DZ7fe2917eOFo zWGWn79Y@%9QWQ7lTd?9ufIVm^&Y7Tf*=RL&8D<=CcctV~sgr-u-JpG(dj$uDt5^_Z zQ~L>!%p;(YXrITU1*R3+)YPWuOBbQeqqwTN3=HB8aI40}K#tkUGazUzY9H;7CfV|o zCML$mYC@X8mDCt9W-`pBr;xABW4bzz zbT)^uX_J4$;g?kjmz)7sQrQCqOmj6O(i)yh?Js?DgzA9pB_gh zoy6kO1x(B=k&wuk`T|wD*X)*Hz#0zRD-`x+S|11Rv2}q9BuU@AtzfGFjFEzWY6c^B zuk|Kp$i)^3 z%QCt=dF~rfvh&cVpN2;M?1f?(@BH#tbl^t_L;OtHs^Ej5{K+5vu|x>u=f|mBfBM#2 zZo!fIXmB_DbT$Soa^IVBljZxyF&N3jVE2wJGShJk%ZROe>J#zX?1mg?u|A{;#d^5m&;4Mi>F^7O_l zqu%MgK~}ILStwTabSQuJP~UyETyuFG)X6POG0RrEvI9Dai1|OuGLZnDm@oX>Aj9=KFm;?-!N2~tEG*N z+^G^X^GDCnnVBcF#+aLAG?<~gl6FH%ETzIhbbEvASlf)NdGmXUAugkv^7rrC$ z(v^g3R+p9#()Lz~5nuIu+*{<|W+rWUE{{RP82qxDnHS#ht6%*JBO#BOTWvpd%Z)AY zm}WPbj@ecoj+?1-xnDUZuXZ^z^zgoMcU<|jTb=If&!?nW{jYz`K$_ks^G8iiPW1s= zH3je7`V(yI1ON1&{&RW$ennoGd@C0dGxVzu9GN=I0qoP4fJ@cRi_PVUF5sgvfbT`tS8G4y4S36rfNTySR^3k8A(>?2$mLkgAx12qd zHT0oOKe4!HwsAdCuZt-mtgq37e#LP_U$9B`C+u(Uk^j6ZFVw%E3?@^jkK=R`k}4!- zd*-C(`SDYf1=yEH>^tusi?^wqolYZ>bPytgtGyXZUnl)tsy47&)$owC)Ob%}!$oVF2eEdtdfXF?!fXF&&dF*@L+TzIbo$vu%LbNr(xYX%`_O)%v zIBmPFowt3_1NyMNeD2N?q{EKMwFsa+CjZ^;7}uctq{wF}Fg-?0BdOrx0`HCFLYh;h z_I+tllNQZ}nGX)e zj%RLv1mp`35y>~VcM?OvCex0zmiRERe2hg*U2%j&kE@a!YHxD~bBl9ujqwA>wvu*f zd)&~i@DaRyDAq35w9JHKHKu6Ne2qT-xk2kd`fhgi$hS~)F$g_klRInZ3Bd?)ip)LF zBu|jxj+I8i%tg$8B5CpN!aGL{JsC3nN@*jfdxlBVCW*?)FElq zzVmKkhR!=fCX%X*{mI)umPluDQ^w?oMx+fhvt%a8MS6T~JnY8pc>i&GWrS|N z&M`@CT$YFq&rEnITxe*4eB<+Evi2@=c{JbzY^ruM#qN9Wg`FJ86TedRLr;PWbn z-V0@B=qlECRZNW`6hrShmR_I3bTO*EW>n1F`wvovm+%Hv_^mBPJb(o&~bvIshsbMki9Hc<0|NGz6EIVw;<`p?}0 z8^BcFAd}CD?|dZms7&o)&L78b?ft!k4LL`+s+VuB3?kjD>czg;0`b5Pwp6@GEAH8O z1d|eCYymXT1R23BDH;VBwuYCVy@-{yEnF>@0-MT;W^gzBYTd%hP90k%9eY(BW4SC; zj!~I=ULvg-i?2$*xHf&sD{is?Tg#xOr19YXGIk3^T=Ob{UA=Y~y7v9y=# z8MbTMM|(_mh%s@1An$)m(=;YB<34>#m00m-rWH&O15FtMa}%zn&RV2OB0f!LN+RH3IfZ3f{Y+;#m?VE_9?pcF*%j?6Tc9CX?;eSNGo`&M)G$CCX2z zQa9zOcTS|qq+E-8jqX{3zF@JZT5_`>7*r@&V009kNvfqN8VSw%Yp=a#3K8SxASOfC zT1|4+DH$$)6m+cBG*K>;B;>37>_xZp{Zl=L&cQtCB%6~?82Skv&=^W+a5OUc_IQqj zVIn?i8WUTA9+U(Y@}toPA1RqN5@u3ZnxB!uq(S88OZy-oO)|ajS52~1D5y165IZM^ zU`SkaLH_XMg>OszaeemLb|0+8S@hc2-ofh13f_PJeW{UiM0CAAnj#``sU6710dqq{ zg)>u}B5Tb|UcqY@lh`q{xYwMQ+H`b=?g!T$9#fROaTYQ-t7m3R!z`KDzx;Fpi<1H` zoKov?KH57=kr44uUJaWnia%5j?XNc=L zIJp0Jo&BdY2j4tvLo3_(3Brs`$Y_6g4~WrKi3#6ooX6X(XYsp#=6{KqrPEN1oIIDU zBxG&y4}bo1$+Vey-@kWHrZUxPb@`hFHz6&p@raqZL`CCR0FHR~g2{Yed1uu4AmV#5 znN{W9^7=)xP|#-cSKdfSpXXH84HC>G1h(xAZkyA1tGR=F_YsPi`Lp)Q=2RZ1gYaXT z&TGh$^74)64H}z*zxWkhj)|kwnbHY2N?jJ#8D_0{?TqG4jEN-P{Oar2B`d_IpI!@W znlRioM8;JVt2REo(WLQlEqJz~x>-p<=k579uWR zOeW+j47nQ3!CY#Zj*NPj!B3+Ant8<2G^IO{YNRvCdtiG)wWERg=*6kAlPU*ZiQo+<94!7`?rSY3_pGek1IT|G>^Bn1(nCsp5do>uJEUmz3ze?3TSV$;~e+xM}(u_euT{;@UMM~d`XN(qU% zy)>0XHgyu+J`(CDRmRmC+uu9!`iQgkJ0)S>aB0ze_hJIq69#@1rn!fjCbbM&ZF^)P zy18lKhc^Yja@xT8$p~|;Yb?WROHtdaP6JEjcX2+E#52!4BO}UvRJFcsXm??t6xJX) zZR_TP4HQYie&K7^$n@^u2jBmJ^o#$y-~WBdwD*XSkAi&dxk=|_X2xuD_{eb zWngv9%_Z;2&s|)N2{P@Uno{v1X>u=}qcPEoQ_Ljuj^`rvyFdIskjNTJg2SKx+9Yn> zv+>@0!7cn}=306jtZ$ca{l0;>KT6^yvUV)ZYDYEaNY=jI*FG{3naGyM1BxQAoOvdJ zI$1E5Z`Eb`n(bQN$@=BUOXS!3y@x36>|$&KH#;ZA4Ltgc40-ZB8f6E?ktct6?c^pciJ4n;RP#A0J1#T#^7I zwk)?9PYXY+DLby!&G*fETB{F65~@G{<%E2$L!ixla_kE_9<$_DCXv8rFOX=Py|GH8oDWcz%8s-1>Sn7;?j)3(;?0o zg+{{6MW2m^H{Mnab7NEZ%`ZQNcRnx!pT#PNd5!f58Q8Y68Subxj3(-iny-$)^!0-igix=MmLFsC1S z??b{Q22QVYa~JUKufK@5-u^i@w+CA-WEoh6p=-&qro%5NXheClkUP@8yR<~p2G6Zw2z2JcmaD&sNKFRvl_Y+G2{Rq(?P3@p+bI=_H$ zV;C@|P$Y%{kYS4MJMT4yo_`a~pVLt(T2d+14F_X6de#y-j{NAh3kSQiv4j1ceYp=A zsRRZUFcYS!+m4k`QGYZh_e#Abk_pnModDt2yN``pLr!`omfuZJv(khc-N`qYeO!h% z%`ShZoHPOhoCNt?0Sr%w8z4!YhS zIUQ_e>_ZIycOqB+iNw$q z%@B&!G)T)HIPKZ6&KIz?zDs+tYu0PB$;NV-Ib(eAqU4C<$*hj_iH1Hr^^zoqmGVc) z%%dnNoyRh>s1=YmCh@hGFXQ^12Y9f&8qi*}bFz6uD%DNYtt!@vDQuKT)6eM`IOW8E z@kF5!J%^cO6WMGLSJMrI#Y>l3q%oSz5g+NS-fT!l%^OqD82Fg5U@e@M$kbf}o_*ER zv{}rJYk1>=j&su*-h9f<(>4Y%lzueed7PS5kepWWCvS%oLfHC1b4>Hn)tD|XYBC!9 znNw=-^K`GNBfkZmG~n2N-#aEmV-@-21itdd8@O|KnJhh97iUu%o;cg$!Fo>C>cau?5D#4&SJ+R*g4#jodFvsI6Y+D5j4>xT@svPTI`>1J{ zeJ|EM?y)vGO)XEtVA=%;>ImI|8(-p8`m5C?$l4&Ho$XoTw7+4S#-wRA0`OvcQ#jR_ z2DJMA`w5ku-R0o)xGD|2TCKN}>X|ros7@Msh89YOafnl@Wa^y@;)G(*BcId*+Q-?f zLTbZF&B1dMB$gE|^YJbF#?(bPh>Nd_#bKp|1MhH!TzVit8LIh}Rs#!#; zQo(Fy7MCtwz^z-iQQsPUZn(esv^*G9H)7q6l)~n(<*Bi>jQTCr>_AWr|2H4ykI%=# z%WplOl$!aMFLnTyhrRDTHMjnhQTCA4>e3=GH8mxxk=gcOuB9sEwmpRFho zvh|3hH!L%cDxmbS){zSrFP>LW*a>fiV7C=pyW|?Gw{Uk=MV5rEd9r4tlOg(va_t=y z=sO=~eGRE}bgq2{mzkR5GQ6hD(HErhwozdO+80tG4PC;(o?9Apir)agoa#GfwaC$# zYlukU82Z2bmx?`w3C*&eCkf*3(W$2gNnGXqBC2J-7>m<6U@2X*md@Y`Twx8d-TxyYk>ll0w@mAxXo%+zx4d<02S!5+8JL#P z6r7r1a3~dDI;}~6_u0i9Doug^=Pz{0@QQ_E;FvV7>+VS4ag?a-)eRNr=Q?-NuJ@=k z=y}*pvP|1}`ohylOk}XNwHX+sCoKw|1}o^EZSK{jg0fW*GI(z+6UHIm^&W>p_K{Gk zm`mKoOtyik>1pXluLbzhC6b+&ZpHUwd0T-^TlTqsy(>@w_y{x0qpkf?>kim|M$QrR6t3<}54XJ$kqQB0X- zWzv-*2H$qB1uLOmdu#?i?gyuda75?{KR=-`BplMN>)S|+G$tmdTqY5Mp|cjHD6WRN zTc=G)aj_6WWmOF;%#4&AvTA8qN~fe{Yv|q_w6$U1FYX7pMIlZ(P0>1DoYaY_Yxw%p z2Ij~Fd3qs*?TWy^zM7IHJHs$^SyI)@+A-;Uy(my_bW2n?9^&d`bT6jHGq6&V#E{iM z@GRkj6L`UgrK;(^*AgoF7Le7wk`HXgg5Eqw*kt{{X?~dc#ecA+SzC4di(kwFL_{y_O_`s@R zBSZ?9Dr;}MzS(lEg<8YJyyb1_BESUOK##nz6#7w01GnyDZ072drXJk zW4Ci;aGcXBVsdN-Z@zvBpI*6x!hS#sD1^K|7X0{n_e(8WM;2DdO2p54mV~&TD0>4; z?cx#bHG@p;PS@wb=XVbGcgXxMq=sHAThjc_NlsJf~I5 zlYM>?F(?#6zqfToNwlUDiZJysCXrU7;iAL&1N7cIZ?FWEIVr|+LZQjURb=gSN>9mv zt1#3F0@5T2nWtc_X-RW%|3-Ks$xuw%JZr=_9WQvS!$}uFodIu-$Jo7J5SBRqn}gD( z$h3ZDO2u=F#Ms9K7RD4$QSG>K4A!C=r154YHhdUT#DTWUa!RdX(Tg_ArY(cyVpD|Y znN8YcnvMpz(=L3{a_{kW(M^LJ8I5c{x=ft~v#E(JQps?G>|8?)T01RbRJDdpuM=gA zP3~NEP1St}a|zupP5B=9D<6ec(;US z+VF|IZ8YScLYDE7Q35BO1tv8fJ8lWjgm9B@7uzP7IQ+fkm$#3Ca zvKAWkip}l}G$X5tkp}qA3JIxXIy^H4SDOqol(?GGp-#H`iqM8hY3xF27I698c{IkJ z!OwsB5egy7s`C9|vv=!It?>T$Oa`jb`-NEpX_A}1^IVer;tIa?v@XAAAGt2`!{J5t zik|l+rP=t#nKC{hYs$YtNb&$pSW|D172(>thVOq0eD`^f6`0on67BJ^4ZnEZVa7#|Fny9&3d*+{^Xj27tcEQACOeST`Ow1bB|*DJwJERY~I3e zj8(Alpow21;1u3uWlI-77q;v$RPQ^VCGcG3C6_5 zHaOrfEFA>6h1;ZLKp|}@3}HG+rd4L>tcmlARaJlI#NqcI#90OWib9?F=&TJ^8!q(d zqaXpY;y4Y-yo^@(``c-qsJGl#1oYcSN*Y;slA0~w!;?7lTmXkac)u7gtonE>>OMK- zJ!59Muw$AJjJN_q`4k(b}uEU8wavT%20KH^1>Fu3ozl2#3lVXCjew z>l4#|pKZ2a>^bh11Psd)W(-|x z*Oc!Rg7`PS{!^1Wo|)Hic|pgQ&uKW%X-Nrzs9rJAaXkt##>vvVIHjiXLNhNIo@uN7sC#;@+CF_l+wZZ4dA=n#!+UHf5KY7$Cf0>;$q$Y#!BarzCsu=O*% zw)w6snY$A(ku(lir02qxS9aTccoVq#5cpfa!w7jU;%DHHMqy3q_c>(S(7yBTE<7gP zuU`h4nWnYFCume{vhp}^?P2agwwJiSyR{3Q9PN|Sf#~TdeEQC$-D=nquY4yoz)awB zrNuAQv2c)2hsqpwY#NTVz_=*3Zkor5X8yUPC*rZWVy~{aj96F04N7?bxF9oJQq`7a zAsc2i?QygeMMF9uMOe_$l#C=S8e7{+;Sn=NesM(lEHRzg9Bbkva3{oQ!CPqY8>%8x zR6{>2&y>eI2E)vnmW`(6$Wpi?r#?eU>Lv+$CVCZN8Pt`pg*E+RCUGo5!wA*B@kB|; zmtst~uk-@c#4IuONn*@7`YlPm-=qw#4{Y{MOT2Kzkg6?>r`RqCOUs6?*Mro=o67 z)6=q~Y7qDf=MwYv`!J=mV@XVB75w+Vo0ANjqt(056KH`6yeE##@8%Mw-+6TjA6+qV z{pOv4E&R*`-t_prTr*Lsm2hJvg}JPbXO|MPn%PhqY>2jBn%{w~l-gqn1FpkndOo&N ztzft0;6Ht+;I)eaPo3&<{-Aq1h=P3QJlFFVA@n>Fi@!sRddjQy)3r&1m1W)*?UYOt|JgcrY|{%+Qf?)>h(Dq zGiTCBIiH-T`C3p8`cb^T4kF}aIq^&`gQ=PRLF{zs-{UGTmBQ*DSq`JoUxnR?VO&XRQOBexkZIGF zXmF-!21>rH&9eF3^st=PDhkS$GH|TNYTk`YmdljqrY5lu6~)4SAj9Fnz)n9NYrLlA zJNfw4p$LrlIufdhS*?okL{mNkyUT*tlRTt9&W&d+eX9)I-x0VNrP9|B*P&Pi+EZ1` z&&|rZ6dRkHfo)VTNRx@JKb!kD_A9Eq&x3*o`%;)Sq!1@jQ>2CGN&6nB*A#@7fto!B zRnJ1pT_W>u617?r)mk09d-r9D*sZNCT)lDy*REbgsThnA;FAx}Yk8K~)op=tof$eF zAC35)MkhxGJ|;OQ7M)rhWnt!%FH}V!&FaF)`p`Vn^vr16>&Ddp*1%QuGAEw{kSM&OkKl-(L^$t zq)nBHZMeQSjb+#(Y;1NMkc&s%I}=(OD$he$x0uAk2B;C{A78=g*nSTj%n;ci$^ zb6T!;e2*9hBb2>*0hr1LH0*ru^;^)1`P_|V`Tp$XH&LtCLoswsJJ?Q{q2F4waDEoD zI+>$!X29Wdgc(QA?>c`YjayC5K^waaeVksCuRzP3b{V_sWY z=+Tc#&o?`v$!K>b4y(|0H==~Sdb%u#LRRdZeP|)wWOj9L!ch<(6phs;&f0CY+KNhnNQQO7bL>8CMPvNs`H`}Fp z`;np^&X?XQwaBkaE2gE%4JWBZjsQFS9-0oD3gez{G4CMb*fK9YEJ^%v;TGDcHWXaj zurWcadnSh=%)QRQrh?4wYHbZ;hJy3wPGe_#7u!37YmQ3{ah0`O_nGWg$hx4Is5BL6 zU0{EFUlVIwhIxqGdwS_q3MH}*`~<<|&nq{b5-3+2*ePnbw;?byu3~yj4L7EMu?aOz zT6h}C#ovZVjFEy){_*5AG4W|Q`ZQX$j@7&ONDyh_)~#C-;`R1T_nnz}p-_;_oCTGr z#Mh>ET#QRED6T|-jy`3 z8-_$rWka!3h*l{Ru(Xa)AVU{cHA{Z53_?(?TtU5hFiG5WH4h=qmwYuvqQsp9#)YI& zNtI!~ANBcr96waXM#lmZrmLmSP0Zm^b^$kT-3?~wLXk{ecxHgDk}2n5y_J;nvu{b& zu-a0;=3UHhV84Ak!I3tn@;0V9{V0SS(#|K=Xzkew>W#X`&>fr_cktS|;64JGc|S`B zGxYj8@`+hoICnutN(VA@xEin0a-Zp5*(Sk@{EBrOElV6N-8l+oE{^{8)KZH4#o<%^ zn0&uGGxTk0dw)}v;~mJ*qs%8_=B$CIFZ^c^#sq2P2TuAr;|Z6Y^3Tg*pdgEN(v7~9aWokVc`eQ+bi_=fPeJbP_RMmxm)e}Mn$LX3Qp<$Y& z-;&n|K8`Ch^lU9;zMommz>cSVqZUr^(V2=EJ8^p{R>F@SBXExY)`K-}X8yqy2IM;DLvx1!2Kq{4T zD~>gTLCkf{t?Qf`DL+7<%ZnLuita)qrdo+5qJ%; zqIUY2+J^>_8A{-A4*kdx?rd_;klv5k-8nSe981nu7yyvM zBeQvp82KiyUA-m)+&=s43f9(EVTQo@4}Ct5p_`W3F0Jchjx@cDruAJ*KHq`#1=#W# z0yaT=QoTa!%Y%S5odY4J*)Syxtov;2@M)(ZDUhMlqhrtGz_a=fw^FL2T&T#udAJOH zXV8Mo(!xuV|152&n~t;uZZ_P_!L3pBlxi}QYK;G)=C{~ z7j+aXI+6+D76b}$?*8Nu!*1Y%AOCB7dSea$?gyX9ds(4Zxm0o?eq-=*zoc%{10V7W z`S|$%ov&_s`@j*YO`^RI-x}Yj6s^nO_$z@p&%qkH?FgHP8gN1U zkWDg+nH?C7mJd=STp$b1Jy*mDGe4oxQNpQ6CzX*%AQ2KCl;>ZkWV}-sy-m$eI(ZxL z^mqoQ63x%+rmvCEP1-`e;h@s6CA{l#lA$zVs1+ntQ!;55?1R#~eGT2GLQQc|JRT7V zyG~y4TK2*WlzE5ED)3>ra z@BTrka;c?a8T-2hX>zx`AQov*@JtOnx4CBWct)2R`UwS4_aqo}sOXX^hmdF^_aVAo zqwFJWKg}vRruOjWOPBDQUk#&TyTMj6;L1zmy1h}s-K`3lpIg|c%{TIW>@nt}fp8I3 zra||mi(Z*2(5o04(Ts^fP-OnTWn-=A;6GgzxV0UB4Bc(~D{jwEez&R+m1Uft&*IzP zc#Sl=Y+!dB#Ary1iW{AOZ=;5*4=dQ9XT|3CP~+)*4@<(!GXg`=0^fXI!3$@@y9yM~ zvcOi5Qn`+64;y&vS1ocEbXaMkXs=!C%g~y5e)=lTPi!Hd&r8I&u+&+3k6j3?*_TMO z-{uX>jT%R!<*{8gI zkMuXNpM$v}dtl+%Yn;j|n4Hr{`}PHAxae_hEuAbM^#*pcx4V_~=cYp1j` zQ>*TVDvZ`wM5wg(HO)>bBu7u%!k!tlAu*VYDf7>9XackYV&H4&%1J?%$3_0+4cOp> zqCqeeBQ=^z zgtj;w#aRwrZ8D;U3>Q+NP2G}y&R|C8rdD~Hn8j&f4yqjx5<$x}s<~Z~oI^JGT4~eE zB?niW^2f=p0S4yqf@&FVRHlU09dhB>mEr>eJ<~%n4C9lbw5B;ynEzH9f*G$SC z)Z{p)APY>5k*PU*z{J9gzxPRSJT%N0BD7@=#S@A^ zaW#x1eK?`|QYRLmW~Y&Q=Ibzb9-w~j1K72qd>!sDtzn|nZENU;?)K5LT^DqM z-^tCjOA|j4q8>fVg;src+zMG9vM)myEnR6TmKp}6j5-@Roti#376{?A08Un(q9SksguFw0^(-7cnA}LiB%xJiLdgTmnuj9IRx! z(1thIh6glLtdR*dp~y;W$3?o+K+-A7ii^o)ip;)^V2u}EoC6PwuD4j{=;5$tgb|QU zet)uBO-*FUwOB;}KX*?r{E}3VmW67aedz+6hMX`)QKZTN8#yL(f)u9UzS`wGArPkY zFeAXRn|Cb3)iKGcLR$FJj7plgg1Je7@w|(EH7SOMf-KTu2#7T@Q1~4bH7AmfI7=Z=-dD#~bt^ zm(rx!{e=3^Fw8vSq!wC&UIvmE-XNwuiS&!#g-E24Jojq*nC9wL$>i&|e*v?w-lLPj zpCdu1_WCY@Uu>*=L!R)`r3=z8c=c*w$pA-ePZ`(*K8regL8coV|SDL=>BI5F|xc-g?&1qE+Bt4WPh3tuK)Qeg3wVb<4> z%zT(=eCN<$-2ONqPEXL>B>u~con0a<^wg_7i(G&ic5&3oH4+R%_+K1H(Q1v9Nn92o zsPCgu5|*YYwjL&M*!Q9P4Bhr#>_+f4a%r-W!2zQbo4=S89kZRb7b6WdGe+8XUTWoP zeilkH3w`ziRQ@hMM+{z=Uc#sSZ(xLhaeQOmU`u#13$ZjX#5 z@+Li4U`dh9e{tL-#vUx#_!_Vq@$QbzB8_ZgAGlAlz{2zZ#u#Dz8o2{<8VN{A6PauV zjd~+68lNp4iVQNeys^5k({pZ#+ozT^srjFo*N`E>?&2v0GZTvZE|L&3lm!vTL$TLr zG;LmR7?SQH$jR0neMyWKSB)=H0F_D6?^c?hsXJ9N|mM?95UTWansh_Iy)9?Mi zB{0SJzV|(xKeL3dzWOCRRcYbr?mmaPrq1^mO?!=lfi{?4x;TeIsfs^+2Z7{ow0>^( zcCkhqu7Tw}74zgrPa9gFlOG+_(9ArBdB3v>GxSTD4OG)rX?X~PYR2tlp$$5g{k*FM zf%lim&r2Kl#h`{=pO0wfgNR%?{JbtKO(Hipg^xbIf?5EqxL>~0cN1*wH{|=qz9yOZ z(o{#;%Fg%D*WvWmhC3*w+j!wr1E1!?`7`BMr8caiWwzudes{x?=}NCXMF%7Xj49-N zNGV06wA+}@8JM1)mN*P%IY2lPUV#=&55vqOw$;db#Hev*(>OX$_$0!zyvOY2gM&-ySJvq^YO3dG> z6=1h&p~f(3LrmE2&Lqp&p)vZ}cbK3bHjTPK8l1M~;K~-m!$LCk_`*w{^Tsw24)`oj zN2cBSHZsKYE}TD&{rw_VR@V_kQke1XQMqnob-#ro8TYsv8@tIAzozq`b4MkwkHvfo zIr67#T{-mrGm|Acy@+xjoy_z=PAt#*aAnydX66t>4;MSoJ%%WxpnyM+1_)P5Oba;!S5U;dBViOzkP8pZktXMPn1YPdj8%FBbOj!TTRbss0at@I#3<^^h1m zLp)Z!A`d(xpM5?D?c4%dj7-*xp^uW8cTD`wufo#VR2ivO!%NEw7sbn|NU}zFtBF0* z6t8Xz%#R_mwsb&4M1jZEGH9_fLr;luTs;2_9xks2GIZfF8}}Xwl!&35%+Tv9F?2Su zx^V;|=-gqhqx*Y$U&ysEqcx%T0LAgss!XrcDx;RUE(DL+d%j<0=x4}${q@TTKc+~} zQ?%by$`kcoXMS>`>x5|{cN%C z2&|ziQcLFwYi!nWrNI-5L%o7QIIvAgW=MOUqt~L;$Q5GX`s{gEGoL<9(?LU-c924G z4|ngqCw=2iG?O?PT8D z2sPFy_eS(-KSrDJOG{*-tLXSJxSMv66z7Dq#!#s>aBoY&r(+IYK5Za3NHOR#tBQ!% zk!mdyFWScZ{4~^*g*$ie%J12q?iK~Hr8aYrAAOYZUwz1K1vVc$QX3MHA4oq_dyjs2 z4CE@9pGx9O&&;Ay*uw74UQq9Ch9lQhtwn;PjR%{GjCQ}cXdFIWOeQxwX5#r|4IgB~ zxdWJZPxj|N3mhNc0mgH{(`P%+9o^jQ^!Yv<9oBY-F22(K9LE80_}ZNagVEUQom39S z&vVm{a);BlHnFCzs7feIhEV72_k*x4jplABTsJmI5@lG>XSaYJHc?N(s!*UBrIE2*uES-z*brPg`Z1gdoRb65`QZ z^N1D)yR}YDYIu+dH)`MH>Vu%PnijUp7FPCDJU!&;_DoFYl{PZv@j?Q*AV&F&fu;EzQi+IWelXN7tw&<$d*tV4v-d@e zhO#6OshK8{Mz}yLCSOzcfn`>=A>Az}G(2&-8Z&hlQrbCe4RE~FZrim&jS_ZxfXTg< zuq`JQW;bh)!>v|p9yV`!(iLwooWrOpPdY1j3>3lC&gOD9pC>PU8A^T{$@8zubTe)G zjAY&%q24q}up*88=Rf_KGzI?P``?%7Q6GKi>T0Zsvui|FOzMNr>}qVB666ApnB-T! zy1I}5@X;#Xv>P~28?P+z+hemGDrKw3wa2lH@`jtDh4igwCvk_&u^)se1Fd*rzS1;G zTI%Lr88keIOwGV-E^MAoA7Asxw2a`cGAQF|@flW=K&|eJ=0B)*5@Z>1bOe6_o>h%Y_ZHrf`jR7wK#;TAACy!h|mOmcRH~ z5)0#sR2ssV`41?h=Gkt0Fs7w^8Pk&+_<6o5=Zs&x#JBP^yu5nfP0(G~gsK!mx`5`EL|AN}Y?rs9N#AqfOS4}?tYN+Kiu^{7#g>9u*r2OUkQq`UQEdsBA&cF_CAqILlVf;cTZuGBnVEBn6&IArbec9F0cmt^ zlbR_@@E%Tml>fFFx6jPG(+4H?LEVYGCI=BcEig`it~yANWh#sbw;NojPTmX6cCX`P zzaEZU$XC%HZ{9O01;On`rJ=+Ej&A1#*(9xx!|;2Ji__Io3H6cGF8{>5OT-_#(@w$#|TEW8D(Q}DzZLiN*2A>p1+YH;@ZbDQyur#%ZzxZ3P z;lod^Rtnz#TNO}Q^*=B7A8p>?h*`!@tym`jF{=wr5Z{# z2OoOi0iFCWO?yW=sp5sxIu<81{Lae;=13zyGv($*2hN|!_p{3sB95*jt+ht4bu3NK z;PNvU@$siu$bD6k!K7g~=MQf-WYBQ4m6P{R?{;n;x~>p?a&R2IUVdg0GfStjv-uFE zQh8t##fxhUj@666{)~ovN^KXQ2tODMPcfJ|(`?ScH)l<3KClr23AP;|#rJ@%6wQ`}_wFUI zR#fm`Ou`M0^9B)V`w5{HJvYzQ?i@TlugU#lW;}tpF$KT^{!Yx&C#|#EJ*+ z8pJR-brFVvYRxU!@&~`rNZl|N&B^tPN&G_5L^I75u#nDl!*(Vq$(u1Ti)94 zv53V8u7h#o6C_AIzog3za4e%@BCC)PC1lW+d!A89hEa|UW>G1_!c@8`{nnzZg>*HN z+1enJ>v&cmmsaHK?5swg6V(g34gkqPG%O)^Ru8IBqLU1`j)!q=`Rprpp2jx9hNUqJKW z$8`P6(faWJ>~Sx134u4JH8l6b2gk8b(IB4|Yh0W@b#0yIFU{TGCcz-3t51gS+&^CQ z|1D+hA>FKEF`L1eGiUJN!9yt!4kGv34OdX4C4GGZcvukRdgu*;GH{a&b3NWMPkFi6 z|LA{|INUZuAAP@%)Q5=F?&)b_oT`mqe%!*&K4cIf&j`-%&XSOF>6C$U^D4glj850c z+PUf$tO^~GAAO_O&2>4CpSkb?5@Tcd@sHmPWawO|#bKeO=9=iQ+-=HgYW0SjJ&;WJ zLKVVOh`p|F(*f(ki7_YQGV`Op^YHyJN?bCdNXG7)-(^>d*Rkc|Ez~PDn9UGHT0+th zhCVe_QX4BpJ)t z8A48iSDMV$bK??sAn-h0QP0(eDI@;(D{hVSsgCr$QE29mo_g$2;>aJt@Do`VBvr?jvO=lzz~KytR%SqrgYYuOL~cj%^@|E&hH{<86s{Ujz#}lw6Uk~rR*ZE-@J`Nu{5xWAN9@=V14u* zOSp6Q{JG=%^QV%Sp3C6(Lu42ELL5JHHoccB4e9g0dRN2Ln1cCf?dUkXZU;uS_dTKi z$6??3(9ArJm8;j^2#E?eV2$#2XE+CW=zajCCG{f*D*Mp6fKrWItgX?xPLD8j!`5_F zHEZPp6x;g7T!O+Ib{qC&`LoBP-_yxjPa= z;BNS1IPzVzJ{EH8m~^VhWen6BP9Vq(69>Y=t7*VI=KY%*E}jwx!Euj~;W{zS-B<98 z+*fY^nL#A$mI%9z<<1&Amn>l8x`aiChvFHc+-(#(!q98`B~2u4108!-KVpYIGxb3x z16h|y(@{MbU+dcueDr;1bQ7j3r#0o(ehOV{?^|-}j9&D&c zB~Lc)IK+UO%=~;V-Ctr9)Txb04cvpLbo1Q(Ja#v0f%ARG zXhEmR7sQqVeoxRQR-;MyaNm;v7?@&WNd~timR^+TbvkL~N-8hE;}>h>yJe2buiz&? z`Kc_m`}3dwT$X6Pd+#2~r7}vTA}-CONWGcDOC-CD^_nhm?j^lXByGGt*~Dil8#e;m zxeZlXkzB``1say1KVG%5M}o{>$vVh~Dp}NH+>b%?)SEldtO_ojnSqm8#EqM`WW>9# z6*N7;O{O>D0O1U6e;;stttwq+ElYFDfer%_^*A(m(NE)zU=A5{?y%$O)kl92k1i(>6GhhlDGD%FN#xQEKJ%--$@>IJ~uH0&QWLBhq(lkqQ zw6NLCp41?*o~tcah!aAUK5=H;+SD0nlS@dP`I7q`y?mFh`DyjA3V;rqmO(o+?D?ntp4oC`^t@hry7Y1}c%kFeN4ovCZQ#w#@o)w&{Uw=2h6 z_2$=(d>|ng0@l@zrK%(j+y@TbV?XVCRCI))+oF&}OUWu+hBd(E-fT2ctyJWom`qo& zm#G>4x|3-S#)%JIQXgr2kg)Tmg%mCr8TPnG3QHg?#0lvs@-O%-x&UaQDt# zsfic%3$n_atRG!_yJC4nd3F=G=8}#3=)*Rd+tHgiyC5P^nD}i^9Co&zQ z@BDxy92KV0EmY}VRx3r6Ds>W4EdSSo<8qO^!_}a^X zUf84KKJ>Xy+{pkM3P5IHTPND{=y(oMhG1~IEA6SJmVjd^SKCyw^Yc?oL@TqBVj`|mpQUP z#$(`DLSyqg=h!BZ$z-IDTr%|h>_JDI_26*!LsQmM-`m}j$aWj+>yn{&4eU^wRFjw| zSKu%cZ$DO@b9);-JE=;Y}~MUEHC;&=}Dg2-q;ev$oZv8peJ^5xZm@$ z)xCltj4Qxan5mqLbe1C~&M#F75g~ib-^mD`zW<@rlT5q$y8NF>vw`L+4h|J z=!kB2Ixaxxkp{MA=GWD?#s9DeD%BJ)2iZMt*ptT-b%c@5FQ$t)mo)JE2@@+c#eIv$AktM0 z!Vprs;rsiey9$=Z6})jS;CvA`8`0ytDD8v3zc^OGnXH4wtO=d2d3oR6m?ttiy%fBD z&cI7&G`xI9#|#6eBx3}!4r4_a)Zehod?Xt5Bkp4q=V!9ZNE<2q)^9wAmDO!5F9#zA z>RvfjwooxMzq?Yw?RgD%Ruh)cqu88N%{{bQby<6!?|UZ*h_9I^ykJD% z|DDra&1x*+YU0x=MVi#}(uA(abi$deDt+`5X-#Tkz0Tjg0G(!)K?pEAHH$i#^_S!G zbFY6FZq*n3HaEBFBnr&uauV+ywcW#3(wL;SxZbmZ>B%w7HIsCntw5Y>E+C^g2b;id z)k2c27e0{P(9yr4O?tx-TVZ%EJT<3bhBWZAGm6yAmq?&vAe4(U8ct8CvZ`7n4_Oq( z^TcfhBQUp*VhqFd8-mfX^<{CAD|WG%! zfpDSQ1ke!;-H$(GOJz@~AsQWF=q=L{s_wW7TEI9R90Xj+!FK)rh1AUZP0Y9(p7-5& zbr}xXdTV6Xwq@RM>&Rj0gd4mzpLWfpvtHI1!|$>QeKD_Np8TT=#OW8uG)$yaX=WW% zma^9)bm~R<%%3{@3M$nqKK|qih9M48<1sWn@SJ-ORrlm{iJ2B|Niin@X^wIf!*!w}p zG5m6Z1iWuQn?kMWV1niVLv+7-PIbEy2NF~09OGf;c9iiCd+zQ=zSj82&)?A|=$;O0 z-f?axL|d)~_xxGfHyRO&fOzpO5}uTN=^HyL-oHkB%M`FMjnT~Q9><3EogW#5r z`sSSvyKnp7OR2x(D{=7rm~#r}Aca^F%FsOX2t(I7jmT;WV${K1JA-`y?nZ$V3PS<+ zX>WTI#kvJD6cdAXT%V_mMt9BW>=RGZ-yDQEOD0q{wO^XjrQ2gJqe@0UNm@7uxMjUG zG#6h#{sX!&0qpC;KVZMgnS3#pbh#u=+}qALH2Q7WEPRHX6=Zhgs&1Swe=fCzR3n97 zzW0#?SsB>Y9iVgz*os?1wm>)k!LClGOa-SWwLXm=Gxgb!E|4b9sfEdea*$p+h?$Ra zEOFXIZuR;duTIoF`x^dkB;DZ_teleC2Vap-wDwB!oE<k7J^x)7QbN zadK>M&5x|Da|N=3Vi7}6kndSN%FtslA~9t9z8&`HebM2ixL-pW)yC{a zP;mNKrD@~Rn9E??{BR&crqr3Vf~mABP3jz(K0{`8*1lLH=LmO>T5tCk_S7LZwCU;{ zfEe7&%#2KtD;A50LyT0$QokSZF42?dzYlM1VRKByg|zM#k8y(2J0v=tqC;PJ7D|#d z{OOA>id}v|V#*6Wjnl;zrdn=#j_L)+1revO$y{vH1cT(gzoz2+go4-4BAEJYWU;13 z%y}jHfqFbrhKu3XMbGvTwHx6K?mNmjg1+lZPVcr6`sfCcLBG#31;!-bw~Ci9Pvgez z2JYU)K;m7-w@UGQlP3Mnehn*|25IUl&dk$ZV~9Y88|hkxnVWHylfxr8@*Lu>(Y6~} z0Ysd9c?Q>Xc~CziOqc^#5v)dQZ(z8WK<;pjF16Z)ASqr z#xG47GW~2Wr#+H#wVCENY8F`tvRTO(<1+Ma!O#aRTG=iU2c;RAC1%R72q73RRPt); zDQHu~$TQPOUidnc^aS*YgHmDRsUkAuuV)`2Yu;fPx`f5_q}&!=^MidwK93VRq0a}| z60LJ-A&c#uWT+O>YUcTMT`1TV_DTvdc5>rQIxa&$p@Gz$wkE&paonhs^`08KV~4|O zWvN1HR_(<8!_B@BynGm~H$vNslLo3}a=$#=k|=HG&YeeYY95Q1Uxr%UhF0Byy8a1J zD+Dw10n%&~&=#jrhGy${^W_(@vAv7+_4UA}em-}LQ`Bsyjg>C*=RM8bpWRnK`xrYZ z2lYiwYM6)i58i0J!Z2!f2FB@EB_mIqd7Zu|Mx7p)n!00TQ6zie!w)}{mEE{Z>y^(w zBjKZf<>lqjd7vtnRD~NL$KXjfH|j9x?^0cn@eC=WhZQ7_hB2%~r}JHs6ROL$MsX|} zG#;I~`^d2!TBHbrI}q@Fl1SXf3aOUaDuy&VW?dhoP-+snEUtcbP?N4Py4jS4btVJTLqVyB!w)rkq+#;kQZ zHTEyqX4gk@jI`(bl03a@Q>P&kX-vHSS0%%G@rB=lAn95q4b*2yH$Hw3H`mGhUQnR! zH)RnOtrvdq$hAMtZ+GyWxiUU&)bMXQzW2x0G+WY=!>KR)xn+j0>%LvAlbKz?uO22a zKAy+RFTO|``DxO^UnK^9$z|fCl{22a&zL{^^fMX7`@`>lA3NJS_~|=8l@aq5FVHS7 z`PL`hFl2$7LaB;}hKBE7B_IEkimzS>4+Sgwd>^K5Y~O7kt?`Iv9(N3bz7INPDDBr7 z{CgNWE~~_&YTN5`kNy;=jAZj8oSB)!cfS2K+`4@ax9K&An3*RN32-T+Mzew2%Pp*I z0e}752IeOfq*F>)0A+L#87Ja(^rfJ=5vJ{sYqUF!P*z$~J7URX(Tt8`JpVZ>IO+&c zK}lvMV`l@Z3ocVZgBTSv zD+Wl}+S$WIi@{SK{Y_Wwx=fSPbnzA{;G3i9auJwx{U)8CtNwBCTw}dP3|&IeHtHQPxFfn&9OSNY<=|?I%f0#+ zfa9SdHvL#bI_~RuWNrOMk8vX!(%e2gIY&M-pinxg&|V+@ruvyEyp(v|)fO=z8WC z@LT`Y|BLQV5?bz{svF;j-Te|i{NMvTr1SmY2S1QZ{npJ}I8I`STD~rh>Mt||{^X7d zlf>}fxYTuER4rrVzFQ~WJ~46)y3hAfC{`aGs@5YvcdxebED4?3uM@Ftzhmd7G<^Gw z9BL&4*RBUN_ZT@NIqIZfRI4qN$=CGp4bDwh@!M}Eq;L>tEKZDj+Shj;&{tpI`H=f| z=l9OQlY57Fe(tXqZ+!cIxR-6K?oAD)^1q%m=vi?MadqMpY2X>s z#%IaIzC^DxP;*oCFp?;hE3hhcS%Q=q`pU|x4CuOh_bygfR$Pp6({*T7NL4f%HkvY6 zv8#we#0Ajv*nVvsR|^&njl(gI6o=_Y9K6Q}b{rp&F@&t>mZkR#)2fWt=SpxngUnG) zt{H5iRwr$^)k1;%;p_wF*Y#`H$h5wVVgRu~PQRfbe|r?vE-y*9M~8BIzz3c7PlqudgdY+#G#z2+j-xuN z5O$d1llR062nK?gU%Y-0aE?O1Xt$HXw zIZON#X%%NC3_Lfd(M!jR^BPX&6%UTq?OSA;sP1oIzud$JcXwq_+XwHzkB1K*V)@}R z9yMtlg)17Sg9qCcEKlfIF9?j&_3*17^=0O97jm5TUE0LZQSEWZF-*H&Z5|gh@7Vqh zeHW#Dudj#cqt}=^Xe?R4Sndwy$7?d>lw(df#$^!kdNm9~7AWFEAD`UT@L*HNU-?c4 z=js@X80j+|t{-O<%sl3vDS4oMkY}&Dy>(PCb`L%_4P7RphgEbu2Hsb3a}$hlLW9VW zdoDv=Y6;Um2y2HS*JAn)KoEI~R(X$!fB`_~MwWrFTbT+9Vtl*6v_s zyNvgKd0$#8wl+8ACKQ)^hmyq=R^Ud$`{_AMVHTHPxWc49%H&IYu;<7ugmLzcjAm^f zP#n|bkv~4CbcE?f4Rkuj{U@}U_A!s)NE3^gOa)`vBu*{nu)MM!$k2TxM}KV;Dzw*- z?YL4`ktWMoDmmmt8&-gcM33%ygkgcMhVK41ENOkeZ6J{N*~*;fL*w|o?;s(lm)0Hk zvSt1?`K8EYyk5AEYgez*>l!}#@FOfQKSYK6!lv1qNw)o4?0Y87vDRpz>NIhCN5@`@ z82UsoLl1)p*T3<>I8wyWpC^gGMVhn>9P?iO1~5gweFnn$?lWo0xc|a435j%IkPd!TO%uC}Ok)c3w!RIu4l@Y_8H zh3FKb4cA#eopZ3A=c;ZRl4SB{6uXPlnq=Utk+YBa=^570-AMK@Xm-M}kZ&wwj3ms- zsYx{I4JqV=Azu^s^WGiLSLoM`XARwTTe$UtS#V-zK8T^qF~KWb;SIk`!tb432T#wr zE)Xee2VL4I7~T;I29a?FjU^5p%XLKTuiG3kh?)0oJ7Vg`%)>P8G}$5|ML6#yt<_6Q zoaz~39m)uIr(M&)GTorp+sisJb%D95&SQIxDI&$Xf6mcQ!$h@5nMXa_y6v4oKrKK! zz1!!cJ}yVlKGchjidBx~I6||9OycX<5G`B!%R3pm97G!mr@NnHHEcW{8itwoX=^qr zsNTPVt5??XFaPj5;^Y@F=m~4+e)-WmB^AlK5-80^%02G&UB_?CpqZg>ugG)zrRp;#z}X6Q^lGnW|bbbolUFgjiLeI`~f zBlBh1$PoR?!WEw3q(mn7JG;Pc%@tsU%=#Q~fumr89oj|bSD~AaY7Cw4-G2wQ9Y*^- za_oqhdDQzN`n7$G%sk}SC-Zb@N+6#Ocf9cSf6Z2FE+fkv)<>g(QbmztVI=j&O zOth%MEJ~}2#P&5zDH>jU;dyM3e|TeK6H$m486&nSWIASs^t#zGEM3@*c zH+nXwGv54bO9@<@(q*(azb4X(G_7mOUA5rI0x2_K68@Wgz=yIW_ep`EVQ|qHr975c(|Rw?ac&c$wD!niRlrG zdH;L%(eXJRb3puYjFee3Im6wP&i+O%#2k0q5irRkj8Sj~$rh4E6AM!&<`?F%O_sra z?meG0n(spA=ysFMw)o^0?LE4Rzx&q_NX`hZqj%f*L2JXTQKv_L-6So5_Tc<=PGwWX z!C*|!`k@?N zV=gQy9trV0;8Lw~SyjFUYG6G(==TFlg_f)yH#L^QdUEh2_d#q}+qS)IfH3ULH@%0o zkcf^n9@BEq$0=;(hK;FT7b*5+ZU0)6rZnhPL^7G8S2*S&gdzi1{oQ7_$PE2tqV%PM zY_-AEaSKDG5%!^@8hSEe*IP}e3!RR%m!lh_jCxc$G!fOW4QI(CI}5jbu4x#_QUrYG z<#5mD4SZ{17H?N~@!$a>k*`%sGcf&KB|kGiv$yXjrT_Z7m$a_q5uc(m>R#On{9G;H4Qf2o}SY?#^jRI^*Qi5I>#R4c{=?}?L*$nXk&5vkYJg1r#A1q zLfx1&Ul~)xfs2$eH&{!LLp?QgdT2*<3^y|P=&_>1RN(H=U040g(DQiOJzE5NmNbZ|n z01yu>xUV+I4CB;W4DKV)jJFnlJ!lw)`Xtcjef*Kg^@(a4W3q=!aqV)H+7vHSmt(oM=l1 zB{`DM|5{b0>bjIz!64#5vzitq@}u9zZKI5IIxT}vg8W(Cq^oXPiJw#Y2lrJ>r%7YH z9HMbt?WDU&OsV=%7d^(JwMxiu{}Qtzg{Pjnh=r2*g};^xJ6mGaK*zt3;T^G-aHElmXpvGcPR|3 zxdQQ?j~D_#W>^h+WNn=zR-LXtj`7?f`WVKd0Yr|uIr`a&Jce#o@xs|Eo;p{+zxY=+ zY3K+=3EhyH9<_R1GM|6_#|p->0{^Su4biyYb%dcqZ4Y02XaE^;=s^531;%+% zze8^HPXvwR8hV(4_#s;@nbMU^CSnA?uX${bW;Mf)>tPPC+h7FM|UGg(qYlJ_lpTb8Yh= z2-l9w=qOx4iFz2Q^GE`4NV0D(R-7 zD>ama(^k=)-i~@LsUew39)#Bu1Cck3cTyfvlXHIQVbi;zDWUR?pD5}ljmNzV(dV82 zY?S2d?9@4Y^J~xIgI|4u2MR=9FP()eTwosym0AT?R&3-+gZaiYNqOG`DW+AUukZYEG4oNa zi^y#slkdE{ec0~@9D79ji%C%|G8x<_?(z`NKJygjN;=+q?}NZLTv^d^4m9+4K5;NN z3Ax{M+NP?C@V@gfV}G2_*J~Sx$2RLW>gA4joDOEK5T8tvtD`$TO}Y+86%=QvDVr>} zGWn|cw}xJN=DH#U{-Z#Lzo_ltCCmR(KQiz?IY(skJ(+{f82Y)^651jzu_n1oE0j+QgVB zA|)Eq1>~PHLmIcnX7!vZ8T#S`nb+yNGZQKn#?;V2HX3=GvPuOh)diUe6C4N6`eA#_ zrPdVKs*r!tVnGVS(__*uMoz<;+mC}r!6-(3Y-k$Q{c)s)FrVep&0)$kdZ+DxEUh<8 zQrrYe6*uZVn~q}s?h1qpJLVy-UG(a26x7wRZ8>t!Zg=0sM>)8#+m$_xihhKls~Npv z+Gt~WOxb1Jf zo+fJ$@cg{$_18;_?@wcD5qaYtK1f!O$!1Wi)`+1GE^fea3v8}*=-IGqg+>yV}=7v>GOSvKAfK4Tk?n3 zUYteUOydWCh(Kce1tu1Hd5vxD)X0D)aP6+Z%%qA-XOzBUIQ)5dX6{65e0Uf`+{>fa zb9A3+kt?EEb-W;3xK&v^-Af}4J(Wtj*-0Jb7u||OM;N*#5~iw|O{+^pV5GS2lc>55 zJz>b;xPHVf*q3V?(NS-nC>mx{Yg6z;(i%l1u?)?sNec*9Qe!6J2T8Db9nRpsd>__a zRzohKV2RAsv*Q_P(`Si!Pt$7(+SmdFY2{pVof$dCPQg($*pnCGl(zt%p&#nF-w6?( z1{@n^O-f8@)xit%I{w;=DP#=xj{~PCU1-_)yaFH0FjfU4s|iux!&EMVOXnwW|G^4& zcJ~K1@!>H2f-Qv_BhEEZX(&iD&UIpdARBu=Ieq(!ycIkahCPU)XkX5;&&yC_=+|G! zej}%IL>{3qbECiSJl2q6 ztSQ#aUH`eCw&tGMv7B}_QV9rV=wy07ygx|mt2H8%J1G`cT1_^sLs#GiTXmmACCNfh zB#xR44h;?xcq7nk`6N@1#Tl7b2!vYXT9X)hs|DSv$_LK*&CO=Z#TyTMDi364K5uvo zJ%Ndd95L^6(C43lv2dAQ&p{g}rmh+CVtm|qXNnlQGT7HH2K*L0wrJmXpNFSD&$s92 zHECX-&ACzPYylEso=<>ZP7p(9raqaQz*85_V0UjnkfAea?6wdt(p;fxqDo4ArIA3E zZf`0PFqRnFtLWA4Q8VO0Z9_iKp2v=Y5f7m*aReCxUQP}pVaF;~8CdO|{m9p}apvX4@wj`eC4 zE%HYt$#%@m2QhP5=}c!$P{GsFy7a-n@$@Mex`qoce+5ahpgi;Z%OnXVky|_sm3-#x zFRxfC>f1Yb_uXHhP%L6|b5kzhH!e&gT_u0JeAYJL#G6?D^&E^ddYdEPb^Ml1DpFHV z8m@2L@Bi?5oWcDL7z0PdzmU^#lYD{qf)4ji>Q}wvlB%ZFz?HQGHi`n@zN{YUKg<}8 z9@|lTC6qN|z_FuXxN(_f>^?deg&1N#85y&VH-=7zdxTkpI=9om-_V0N`dPPDXgn$| zU%mv>Y~jk4n}OX(b8)*IF>q(Oh12uQ;N4gjO%nso?HnF=#OHC;)ZQmZv>*A;Fz)(j zAA9(D@Q^GLZrI%3=AuG%J8fBQlRGo=MDnP~ofWu7qlq|lgrT>prz}mam@-t+X(!LY zq=8snX;dl$p^)!T8DMg^{h+vC7dXsgraJjy_e1ThF<`bEAQn_}U#>NIpvIw}@;K=D9^VPY zAjNTErxzApAXgu40tja4YRBHs@lsoRHnCHXfdUb7@OwY2$X4J6?b-sdH)pm@88D*dabOi zV1Iuf8|&+2Zf_9dX~^MSyLB6j$p&6M^%Csr9<1%#hp)Z!!w7g)T}W`jHHd<2vb#BTp0mqcw#-tN5RMHTZl3zYC%+ZEw`~BF;OtH9Ys zm0sG>afPKr_aMfV^fR@G9LJHkh6v+tH67Hewp3<2J8{|(??Sq)6PfgpA}qYmxB^vl zItncFz3*B0*0&gmnbV84uhM0DfW5gEha6!yILsvXtr50IoD^)>^-NxM17uP!FNdLKWRHAZl;2BVu zsjJ=SR&vj_Mimq%e((1*$!u+7vhu-4gEI&ez2BC9)kVw*?+#)TGee?oY zGp{v22R`&(67kSJLML(`jA&+P4xT4QohD{5n|DwmCH-4xlQNh3g;`gcW4}2k4j3xh zrS}?}cct&^S6eo*BLhGDgYU~=w+}veUp_;wBhKbvSGf=V)32 z%Uc!M*TbE>6vP%Lv}j}KxE9g#`zU>MeHUkLk3s{D)kmkQ<-|Y#$h7ZxmV}-KScdS` z_Ubpdj{%>(zn@>chRvjnv9U3^UsS8Xg1t=JWQI=r&)T+%AHJI)3oh`?`Cdl{_|8LI zhcn1`9_pSB_ML~~Ry};@J~hdI&VVvboA3E1_k&|pQWnzLtW5vzq%-+((`horb9&ZX#;wZJ3m2cn zFgPYn2D3&C-Ng3Jwq)pQYioTfk)i!8eI!5$RKsaZ0GZN51vFixsS(A39U&lyPb|1hJ5H_CWf1?*12XnzR=VYAEq-- z*MoiS1)uK3bWw+@hb|+jy#)AjsY242j#N4cBVkDUKRfmrT!z!yoGz$1si8NlCs#v{ zutA6(((F*@8PLb8r&98D|rV4N!a)A-$T7o$A_yg zVyUU&Wj4LHNLn;IB*uQ0v^e*21lnHT$o7c+^cu@^(@k7VRPi=xEUQ7?cmvT{HGz=# zk?-lh{n$o6CGdB@9&ZdmZI1ZPM{rMLYq2Bsor|u|0q5>_Y}hgN8viibumAP18gx|u zvFHaN6ONSDJ!G^L{`{Z$Ha0eQ@kf91ZeSbUKUg8C)~eVmn)ucA3SPLRVPi)_KC2*= z;u*X~4U+}n5V#9Cuf{rQcWgKE)+pZVulT^+I|PuG#oXC;ck{3^m%BpD5arMz0&?c-7YIFOr7dJ#peppg6>cW~8C#Gf7O1=OQ)b)I)x; zMqjVhP%f9rRnme;Pmn)89314~4l&%d90$c1kLr*w-7M0Eq$8Wngw|L(Ehu|c_Z4>u zh$DY|PU*;c=x`{8qGQ}cLf_jbYacrzER1lknaq>RErUqp&wIA=RjM|&_ei0uM;Jro zIsPQfi5@}<*V-}%K%NWNZSA}1Bt=~gJ*YoJSG^b9hm=Ysq}j1rt&@MiwWYX0Ktclb z8y%5)ZBsm4)Eka+w>~d<=$)^)eT zuHyEcJJ_z%WLtV2$S)!e#fBUm)pHoeqT;nlH_GKDj$U^}t`EW_N>k*y0HeI`*D>9Fgg-?34~(67&seYE%NUh^~Jy&Wkt7l%ei z0xa;x3&7=b2ssva&)0QB0+G~eP272C;+>C(sqZ@x#t?K7qZKft{w&byCEq1Iv|1BM@(U^zS;tEX+@2ur!+sEZgcgJ}8SQP^QhTRBK_k zVxe3gQC|OXP#nh4-F9RoI^LoOmyVu>0FjY@AUd^~?1(AESQKF)XKW##tdM0Yi)1p` zO6O;J_<^=XvPvy)5_50x3FBOc6Z5xTgY()vqPcAo=j1%}Hg)>b{TMW^(%1nREn}Bj zrnH8KjoIm@{yuag$sxTe%#u96kx0m@UL5J0NFCmo*@vD;8Yuf0ZhNDr4UPX~EcYkQ zhd!hPHqvv)*{r%gcaHIyadL}j(IQe5;Rf4r30AI$T-YyQcPfuH%wiI0m!-$ha7;A` zo0$5;f-OOkrW4Jm~BV^_R(XXTP?;-AKm$jrpJG z3@Ffd9`ar)!o+Om7PfOLre~(53y$4!LBy6mUwzxyQ6%!*x8Lx(jdV{BUwhA}_OKN5 zULLgd|Lz~v-c8KRn>8O_6#E)DoG|4 znm3yfIc$+3=@>QcP$%>o2ggZ`L{^ir-NDnK+dg#fM& z%#4)!c6WC}x79oxX9k_w-XF)>ZUqTb#Y}n(PKzrl^#NCr4_1|EbZU0CT?FR(?Jew; z8+cIMqUmGdLUKpOVvMI_M$ivp<^gSnp}ABQIbpz1T!tM6Ygyu4bF_P_3HDN5Sr?eg z3p_m^acn&{<&lcVqZR~$j+Jx_)|6q|4!hZpl41&_vG1tQ@H|qJi?o*;(6Y~CoS4$( z%O+MKzPSS~65crhCicHeMdONs2G?S5^dAFp5Kc8M>_-O?o(r>rZec299Fq zd~~x50#-9r2{PZVPVHX>4cf8XBzZqDPJL3Dc`q#~=E6GkJ`D93Qy5Cu*4Und+1Yt% zK99uE$*;r30rm^~vcG*a8e`bc>Y}wSWA~*EMM#DV7LChgcYDtX68`MXyP2DkFxY(C2E}~ki zT0%_)X=u;OU z5*cW@87Rp-y~dEvUq`0Yz{++3jd~65(S1tOv^YE2=epupM0&LwW-<5ptku>@HQ&Xh z3#XAQn7DTR7J^6$M}FZ7TG+QXO(bXmH%&zbleX8vAs*l7dIr(R87_u+9>cWnydO^d za|7|mf23W%l)3?3^kcN4$I|=ShfaU%`pisQXc=PQXP_pgXx+X{dVmf+dx_4a)B0UN zUa8{ZrTf_2+Cf;7fzmYhB}yeRse3Cr-n$|&H7Srz4;WJqI+~^y6-34vxIV%OLWlbZ z(MBYtvLzUmCIt{wQ*Nqul^p|u=G1edN7GU5StAv@^I`U)V;ky;CDcJ?9azSj4WQ#)@Ix}sxyC@4Oyv$$u-f8XNTZZMjBsi51t zMQm?xllFQY5AHvZMPRO8y^3P7h&y-h$OZm^mBduqMNe~OzA!3}KQ;_cF*G;#Q1{-w zbS8_%D)5tcg4-$W!WEhv`);9vwUmaBmlaH9Ra}~nuoAkoiJ=4GMqyfvV@>Hfrz1a% zu`e~RwY|lc=(kl-m|2*;WY0}0oLpA20Bxa%LV^TA3I$4QO_Rf!f zB=`8A|LkY7wDOhDu3&3(6Jbf#`6eGQ2T_xXj)$8LO5}_Gi{EzmBQY$|<6dphU-2T1_&yH|wmSlf_dgE(B~x9rQ#h(W59!OQwZSOpbN_=8*Zj zM*DIj%=!B=bX{>QOBj+v`%Zk`pn4T)VGaFAelFjL4zL++a-yL>S{m0|Xlg9j`Li*<*apof z3%-Is`Qs1d!vDedzc0=6*RNeeFXG@ZO(mb2V&mafk=iJD|AD|vPQ}F;qvzOzsS8x1 z*WY2O&)n$M)r+Z{n6t=AF_xG2s9FgwT#=-;!RwKa->wM!n@@DSc|qWX)19XrA{GFB z+C1vEecMM&Jrf~;NJ5`KM*Dug^9X%7=+h?Ry&VcbMoAC@U&QoR{{uKsR#B3!`;&zA z2M-?L;lm%{{rBIO*0dl0=xr%@he=NxJYFH!yZ_oRG_hA`;N$B_(n3|d`T|*Wji?i> zx9>dGG!+A$&7fu>o@1?SOUTy-3GK|#ZL)l@Fy+)rr1iL33`4$-PmLp!O&@MsYmhaw zjK$M)^jpe5hoc!|)GKNTL46r|InlJ$Qj06EZMzpErun^Xw(al-NbTKc<^nwxL8o0t z^$Vz?kAlgB{jHNcagl|nvMRdny&Lf87Xe@)t-FYh&)7}Nl(RF9 z;7C@hb6}m2kgx29>++$?Qsa(&B(>YIX~TdL>Z1BG^jiMuqS4ynQ~v|%l9~BGJ~*%K zomj|CI!D?{Dw8G?jt)U4TBj>$j&BV6&-cnL%uXcmNNL0p*ih#W+uwjTp*HjOTCioc zwr@Q*i#y8#?|(qJdOim-Q{xOus zhxjM|=Z{@ea5s&BKCJc|wvR){ zig5iNX*b~eIDHIxPrIK{@^XZOAccVeQIHrEZg}*&ADu9wN#T4~7@P!eL0)!adynD^S+Drx0gBv?1yptTruuwS^D zOZUl^7>`%yw&jTi%0J55^WWo z`6O3Z;C-co6nU9`K zaqxpCORF+*v^&4*O)vVPX}J&8(9vK#_o^wQp&u*tVVsd8R7c5xN6}a3m^w(Yo5&S! z!rH}Kk*zCnG~Losx>q^L`5a=y0F z#8Tct%~WBKJHXJot|cms@Hqr^#a53mpHp#_j{G;CfYdTQw*>v|n;Cl%Z=#i26A!i= z{NlEPH=jyi+^cclYb=jS+dI-n(05_mKMCt&6q?&ev_3>8(POWPDk3=+`NemCfwjB) z_=E3#gkk8Q=DBZ$a${~dLOW=5cb98m9#*c5BTI8Wla69OJ^UV*nIFLg81Zvu-+6J{ zlqhkMtiuN~4^<8Jp-&JmJ#4L(7E>=Mj$PP}BmNslC{=56cBhgKhvgku4_(n!xl8dw z<0yBTfvj|8TGNp zM1mycgk45bw4~t00WX6XdX`K*Y4W*GW;J9r2eT;?mliEt%oZ@Nkc4e=x|u6Qo|@26 z)I(y%^Sy99%y@9E@D@tsPg^URm`ZDy45g)x(A+)*kxvU&X$^L*EZr4yAzEhJ>^P_t zkwzA*q(PfmQbm#kgHW|zJQ5?mj-w|)d>U$9JVq`4&^;Zo)h!hDKj%}VPFfH zgoT-zX_>jgsidJs*Wm;A^U4``is!uT1=o2;4miL2Pd24WQ@c^!} zOZS81ntGM)m8rP>eVY#Kp>H*2=UfNx1{#zl-fR*pA} zbR6WTJMQ!MXcJfXAyEq1)(&!xz*s&jO=0X8KXNMX1T&Lkn9S&S^I{(7vJJd3T_ugQ zg|xom9@sk28eUvXVYe7=(fP$+eDpL1npxX(aBW@1)3ap4&KNz$)cNT#`Of|0JKGRL zZ|z(|Yrh4P%JtNQ4;AKxQ81diu4GA|wQ@i%5Nl z(Fj^2)4t;|^G*#qQsi{NxQEYa@BC;XjoTPYWN`7~MQm+thi2$ZR)-ae=eZw18Gq!M#~Rqab+0?Y;{5s0X$OG}-OfD1Epyy0MJqKr+Kz&$Tm&^W3dPv$Mc@}al^sly-dAHg&Vra!3PVY+z4RtYCmzkOOd zCQ>xlo;sh0;*@dwHbN1v>t?elwQ)b#Gl-cdX^v;oDyAn$c%2Y9J+Bfo7nq+Wt5iZ@ zoc`{_REZi0*L#fy-_IlF_Wr*{Brk)-a{cG^3dhg5fHDjw!$IQyElZ`7qzEV4_2Zei z${MGv@qOhYXg(kn*+LmZJyI@EAVb$O<7KO|FF7{{FEN4*n+M8dR`14iXQ|^5z>Mt` zYwt*+Z;*D*IqB)72JLY`Uk+mCVHd~9q(SssaaLHT4 zz{Q0LOk@-I%je6;kcs`$xF5(>AKWpRp>IVmtr3`@2-yeAH&evWCzG};GQ%eLy`#NKhR&MF^GgY2X(Rhnvi6=@9JpC6Ux**?Z)l0tjF9|+g2f`&0s9eV5f-U+-HJ(+pby??+wa$ORP z_U5=IcLtN;{BwrJYaN)}Q<)?i|1g6aW09T-Qgw zi`GXZQ+rT%qj;v>e|wZoHt^!vRqSmPTxeFy3M>Q6>(roQ{eaKz6XY_gw6=cvMO|v$ zzxfpnS(@ilq@8nhHGWOx-B2qf)OO$HS{uRqjH7!;O<`u-_Tr9(M#c8DahIWk)3_T} zdk_pLlN~#3*{+fMk@+cS#V{nS;xTlQ$?sZ<779?tr{JJCHQTV&otE@?OGrA^1;=1B zOcw;K&S-JUV6|JCCCn2D*hfta;=4#pJx$MNob2cqa!t%6Et)(WxM+u$tvV;R*?>-F zr72pmW(Xg$Y|dy^!rer89#m+u*IE{umWHHX1K@K&Y!=gLstqr)rE(U;%zbj}oA=%z3`59z3~Wwk zM*i|;63kO1#E!?5mOrP&S$d4$F5Tr`sXua^-b}% zo@y$N8g66tD3GCVrqf%QVxpRL)PF!`g=e$b)ZZ)am$1FLi-u?S_XjXOIqrV;P~*53 zx|itec191r(qKTEmMqROavDbS9d_akD^d6Q9H);y-zA7~&nB9fHastga1o1y2;WC9 zN|99l&9g$LaQ!gE@xJfK&<*Ljsc?DMO@X&=YxwFp1?Q(akB%`%9--#BNM^ z=pb1#kG~ULv#<*eQzDZ+2>>%+Fj8sqs-kNR3@gYGao}7ka3&olDFoW?eBgA(D*2gO z$06h$Gv$&BvYv~K*I~PQ+_2`tCxN~o+SM0{1aTJ*M&`gQT?@BpMTgYy!;+>_3Z};u zEX)Xr%YN)Bm7fE$y_D=j)P*ahXh#c~Nf0X2Req(Ck{thx5iax5ITXL3?!UbL2)zs{z!F)Mi7PM!&7asB zbQEpL8Gd~PjX$uDK2i7)?rC4&d5q`Ms{l*rInmD&(Cas%rFjj1?weWI4FflBB4Av? zE4HFatD5NnD3wbs>=!r}J<;3B7kO?tN85_w)~M5?zrd!0u46!Zj&9#sHc>4)GThbi z;=$p#H%H>OQ|B`av+ewIKU<(&s$gSn3zJi0n3jD{!w4S7MczUUUW+zK z`zo2;bom~t>y8VwrIv0>O}%CLBJE?E8&Q}_P#?!dv6=289z*xR-2(DsqnJ78NB)S~ z*mZpmN^~VSR6{Vs?-Il^-*0+4`x1aEMA+(Hjj?(PqtT-(_ z?$ajr?KlQz6gUaCMQuYm(ZvWPB~RQU%Dl0f&w30({X!6$9KO0q*I7QPCqob zA@60h=XraB#jp5en6Jg01qD_RhLSl^8i4m)qn#|LCa0N_vtsZFT^@fFV)k33TOR%v1V{o2~ z=P{Bo^tK$bdzlg8%oe}1_^!AnceXbA1zB{pt@Qdna+%{#{FB?Wz{I|F>0ejq2^|H~ z3q_$AdR3dWkeS|545PrG8B~5^atzISOXkm+UAgDuBxU3$z0z=eLB7A7&9PqkLzOhL zV#PcfL@+AqlIDkzz(z8;1Q1)p7_z+>Q9tc2eA%p{pR8`;m6+ zxhTPvbsKNr1@`*^9S)ahE+Qf?qgHP8y~7|n?~%zjWCAKmG8WRxT;&Cx`Hvafu&QY zXaeVgPoucF20m)icGbbXJz5woPTd?N^@pT5b7NG(o1|lk1$b1~F{*xjMl;NqMshtp zo=3#}BC@&NKksp`>lphU>14Qg+D1MTqKUULDV`?D0(gTM(d~yeuHOr%Odh@ay#wI_ zdl3lPfAl`WjiKF(R7jbT*DGGCi>zj%l6KDNYIa*gPi50c=MLX!H@L7Odt!dt&QDj= znv+PE5re{+++Ulp6NzcY43##0O;=>T96!`@x$4z@KA_APnQ?O2qtdE!ATl;QO!uK; z-TQ6WaW}junnEvWJdS44`El3{uWJmEhSc3Q;`Jz214(A+S`$l4#L#oWQh&R8pO@;j zO^f2bWay5Jqipl^u+Ovmd0@cjetit;J7OR0CQ zM9@7Q)LbA$6!#$N?>iTx+G}DkbEb*BgG;9!F3@(*PBa=I<H+kB-!rqQc3zW+Pzz|ZFLncv`FYSp?drOIXli9<_w zCrjo9>2Kkjbs5U%xM(@-9OXplgeDQfEZdHU7#Cpz4+S7I^yESB$vSNNUcZOwC+4Ph z=Gc*ZCfroIXrWbo@Q!xrgavNG9<(0A##YJ--j8!`iOsZrh`uw7vsY z3TGxA%+1ZpDr`aMaT+6mYC@))a;@*HcNFQ1KQb0^=o4ZWUui#w2#liVvm3_ze>kYM zb0mDbxc)h7>5jk2I-IsfFZ1Ap*@-b}PVXf4pBMH@vS17GQwg!_^-9QSSEV z5KQC?PyH4KJ!6heUz*AwpVotVai@PrI!v=g+Bx~1_A4fK%9ex){=(2OLd6N4P&b8` zPr6b?M&Be2T_G1)UZTJSb}JNloFCY=v7=ylae{ z?mZU7Bx*RO)$x301M|t645Cq#;NG~5D@&)cPBMwSzgk!D_I=XW%@~8}zIgtdb3hdh zYHkVo?DJ5JbhN%=Xs-ee0!^h+$1qIWIMnmp9cv_1A0tRH>U9l~uB*$t8snZG3AF0$ zDt0f*=CE57S5AVhIRM1AU5} z)`4ab+U_-+o1Vuv-h2bU{NPt87E2gJ>_b;{r7aZR+-zcb-@<-1g`}pqATzzr*XP~} z)qpnr4AjgFj8k8NlAVV!`y2#m=8BfY{ty2ln%mc5SGMGa7K?h`4=2N}5kU)mOkh;(F59PT6hzI)iJ(>;=E!A7M> z`_!fYoj_v0<>sD?6r3jU;c}x5rjZ-VLNheUD>GSFXyTZ&ovmHTH6dCvi7hJx(b7JZT5U`y$N3`!MH#1NC=)X23*wiE} z^3R1Y0O4DD{C6(T+c3K#-J^~}OVDIBpd=?GV^?zv96d_Ro-9j7R+`{X=!8y)U0x0e z&e7bSvV=$*!qfq~g7x6AnO`g7_%8{Z$B?hg?p3c`s@%BTV}cOhvkBx*kKx8=Ds}?ALG1z%#Qb@4D3t5+{U^5+oElg0+s~$s^zW0B zo{|hY`SkCQmY+uYxxdUMji3<&_i1Zu3wJ)eg16uP5pLeNf&bx~vsjw?Ci2zahhm!j zuOq-3G5Dg6{(VF<57T}a4O+zLcToGjrBNf$aakoERoh;lL-u!QEyb|_968_N=<6`^ z%IR?(Y1~Fy+{LS}K8wAgfp_2iMPNU=K~^wYqpYFxT7Bym4u}=t@BOah7A+c7I=JgO zh(BXhy}+^SjNY7O7-vCq-iDi(}7P>!tUq!gBWLAzpKAXIeM(X`2{2n@eR$ zRoiJxBJ49@a|25s5+2Xf>8l|cuAkg8v~=N_&;*c2(1~KPl-G+aq@=~16Q*%5Q!Z0@pDr9c7)D0 zcWe_AZxORD?C;C!Z#Qn-#N9i0<=eXy5 zK0He_yW>+&HRs=YYk9f#*&nGwDH#d=oBIeHlBR^l(u|yjB-{eyelV(j^9b1C2 z_!9J)%krg-pCK)MvfW38%vH5oO={z;ng8U+KgR0H3O@bxQ#4yG+3(y`9%q(x{EZ19 zp@h4hzSl0v867hpW^Ru{NQ>1+hpP3+&)utSJWGP;r8y7#JTW9Q7XyBa(2p~)EvFn? zcY$FFhN_wZo+9*F*iMq zed?%OD$+C^9JuLEdfzu!tdoY_O2C?Z1$rWj)YKA`>@+d)(=yNvsR4NuO1F+>>5 zDCYJtQFJ$5Cp~_v#3(e+$y}NCVza#tgFt4OWKO#6meFpu1n#YJaF~LNXAz2eo7){= zsOK>Zb)`4Vk~?gjiigu?(aQ}uFBTzYPF6OeV-$@ zwIBU1%vQ}&Dy91F_9N2J`J})5yVlzO_xCJC5hgKe+eosRMwRCFy`2K;wMLtva}F}+ zqfgCFVuvoYR;s$poC5$kfWXjQhE6xAP-!8dD?>5#sL`E=8;ATZsQu$+=A&qj;h4Fk zR-Gnj9T!erKx%FRckbK|#n9!;Gvlr9lb}lGbo0_*gO;Dh*z@1=Bwx*|BWz>i=1plv z|G^J_Kmuh2Km7g=q;T2j5OQs<*G^`CX7o&V?mfiD)-J5CEJ4j{u);9(IQOGVn-HUT zzH$2)h4y>o^CM>F0;5@9-CqyWN3Su3=%b(37mlL)&U=la`}2kQZDPiTTr08?STi_t zieX?Kg;Um=GHvabpX#!&H(v>CI$CCaXzw3IWPJZaWmPqXbKAB&sMiF2CT32SL9|?6 z%=b_y-k8m%rJvjZ^o;q&!asLV=1=RcaY-QmG7HQwdJMu6XA22Vi7!9P-(^(ynyB*}dID>L}ze zLk|ZOm~3^zfl6SocjDYOX|TtBMej}bT=RZik4Vb+q|-_!SO>Bf=anaIOWJdX^$hEOX^A8-sXI{9RpSE zrtRmAYnG5X_S{4*GuS@1q?M+v-WiUFKrcCw(>+t|B4_?!P&Z^>MHq6Q8PD0R za=D--1Gz*6d>TJgS|}+mt=e<}lmeC*dSX3c-4N#vksV!=7^%}$WD0aATHNJUsJrh) zYk<=v*?@H0_JRwZ$ZURx<2zsc1S52VrDtdj^ypl$P`M0iDARpL2zeC;_I)_82?|}Kn@8bm zPK-J+^s&h?SVy%3Nh=1TF7|jYTlNOw=L|WpldG^vidS!eZtTDeB~A!LVFPX2-H0StN?JkP(Eq>u#V;~y|H?DZ z;zE<>A`)a5&mq#TRNW_rAwhxqCg)9Bd|tf117q72I5uW4N~YfNdg`xTxIjz$u4?zn zsQR26d!(06jJ$1Ia5t`QeKfS~4VBkF7tcL-x%N8hs%rQ6etB-&vM;ltzjOBmAd@xV z3tw>2+-^jwcltA%E5X{P0ReWMwp(|p+3(4bN@ ztcV&~q4X-NCk%b}!BDE#iMbh8z1P#``Zj_TD}TF+CTA+jA_szb{9{wnMNi3O>Z!Nv z8doQ)#x$hmZTS_@%@i`>_xJ<8iA*MEF>BLOM-YQ1=YVjOq!3@t*3P%f5k}C?Kz;;; zdSF$+~p62xWby;#L$UHQVw?_GF6k0ndI}A<;Zl#A1d}7f9_Ck z4E??D)h9pkiQ=YiR8i|-jE~375~>c!Hb6Ga&9!ZQz%%ocwS*xNltjj-#~_0?gaX;q zOI52rdJHYBRB0=bgK3 z?$?nCqvZPVefLAb48fHvSD_m@UbYTnFO^Dt<@=|$oHtq5Suil{zFxa{$wC(IIfvRJ zWb)gufM;rfl6pgX(ED8S@;qGiVfH?j=KgNe`_XgT0ifPis`j2|Z@mV>!&uBduH(e? z6^N@<4mYLsoSaR&k>f~5WmUIR5~3!+IWNly{*G(gMFhEjC?x4wRo0e9 zQi}!XlRV@StGhlSO!9U&ZU246=d-G+nHD-Hn`XuKD6Y=}hA4h-u@-Wu!+o^K(haL> zCa3-!(mqnZi?tV`&=<5XjmIOnxhnwS%o&HFlQ(<6484AHD49$_GL=GcI*uz+1a2!G z(~~l+pUB$h|sAh2`5yutE<^* zTq)N*g`+u%vPd&c>lh`J(NRbuMsMi)76OWkLWi}n;(P(#`*VG(sQXH2ElnLy;1wuG zj&GL?U4yHaZn7kD?eZemcU?F-S37nD?dV6(oPtuJ0{L_vYN=o;i9KC2+R{rXUo3AI zVLax8SlCuo^otz(X+Hodu-W3pLo}m3q<74u!H~=FE3m&rNSwpg zDiwZ#EcLp{p=-^ww!X%nPk;WiWch(7kG0SW)qg^r?Hu=2A%J$LS=hV* zIop3k4AdW?<=pg$FkJQ9vAwAKF#DgI13}*21--VmbJzEx^|kjM{^qu6hqh+Z_s-`x z8~bz~Z*>_$Y7jp1?cWCL8wvQ#XTR39J3oRtdfy7g0wgmUyz)jK&Yn_WV@rWpOoCuQ zv>!u1?+5Jd!`qtM!FJv>N4IZPIn`^aU|3FZoKObWo1Jpa87@Z1d}bUq(vgN_GRup% zxMV7=MSi~@j-6bfqAUhE!^t{S#Zyo9SS6~F`eNv&CJa+nt3npr!hmhOkrO1LXjKg~ z)f&98buDypRX7$XdsNwEtz-LoI22JcS8r5^kl!DLlZM^N5Oyzs>iT12c>g*Q_bYEsv&x1 z0Sv*3tsQ&B%Vwupsw_n0jt$Q}Sp$CYW(nd!3BKjDQop<5 zo>2aHN>v;<_N^d?CLnO)gOIzm37`ApFG4PrfX%f<$mB~<%~xPyLWQxYd~gVQU~SDk zTAijp_VL^<`snjL?;k;%p2y%N4!q_0>W&{&0vT7#9Odr!JYm4as1BcWkqXu^llfF1 zYsm_@u3x$a@VT$b@ZPtX5Q{dbxf(w^P-ok@$LG=T-Me4H&Z-9KZDh=vl{^Osq>$OT zva7j@jgP>g)5jnfZ8YKCT3KhuZz3ORGY&7zf~5NL>crtCRQ07{K-3pQFQjFCV%k?J zp|zhbN%dQv?0GwIzKphX@+y`&^_>+1EF&{lQN3P4n}eyFyCvj;mQw{~jiZnvLh7Wp zWE(_ZOsjh;KTp(;YHXj*v+sTN!yxMa#{b5nekl9Ab+n7JEoqp`7MfQ1K^^B2e>b|D zpI8-+{|oyiPINOCmbiG#!kEkqy><}U!3c>fL9XBiz7WXaY5uN`ov@j^pEp{>$mb)I z%|k+Huz}yl@#nFwgK7HoLW7(eHS&Ty2cT~6o7%*j_e%S6PkW@k1rLv>YtzQBq*0Yl zDN2JZG`rENk&l!xtPaUnERhmW?8TOTyPrq>`AzG8m9nL7H+02HCq7}jP{jCn|gu2|GzlBiisePxhc%rw&4|;6Gwf zE9(-f-DP;&Bj9mRy(#1SiOcU~J2!10kzB9B))Hw1W5C?IjO zg|-5zWRf%1-CA2k6=MNXlF2Vrp)9eciEL%!c0H#%aef>Wg5EC;#vtf+J{LzIbG~*Q z3$4plw4(>$(EKQDD2A&X64q&~j>`znGTAC_5~Oj9h9$6G``dUgo9=-ds-UL4g2-G$ z)jC^>!K#05mi66YEXe1A;Q)KKv-!auTs~g}9c|}MK^FqJgy3mmGeyyu^cSm>E0cGI z4c#Fv7%$+XN>5IWnT`sb-1G^dD@_cYm^qb`+g#a%64?~!hS0^5w>y1?d{96I{`yYY zDlZq=4b1OH0&7eCO4Wmq%De4vbzDCh0OxQ4Fo;FAl~;Q^IvLu6C`zqXjdZ;YLvQp{ zuT(3Z!q#Xwq}mE1^FA@|dJqbl?txoP040)1 zZR$|SQH4~QGsIDaHIqQ6-2wBe@i;T}`cS`gD$7+!b$d;loE}G}uaY^L?1q{+_2K@! zgPUj|3|;X>GI)cHKp^nvhN+LB9p!rnQ6+aWsA7-tqU<|1HJe>8o1p?!EB1GAkEXkNM+L%aT5_Pa;D zI$#<|5}Dd}m**RRVBV_dU_giC^99&iZ{$0>1zBwEnPzEbHQh3YQCmw`H&OL2!)sS` z7$1`@hTdf?175jn{q}lXA!ESyauo%3)f$^o#lv*^s126@5@8#vN|7M1+2jIl9)3CI%3M;qPIMIT}w()8mV|V*nTY}<9SYh?~yG{im z>=W?q5BWG}QOLK8GNniqq(GeQ;+CiS`xu$a;i+10`bIWVpEnaC};6Wa#_F%m;yfy^O(a-){T3T|!Pj_rhs1 zsI{iYv6y|d-E(Yz)k9;JarQ3r3-7OO6yKu$)cl@1mcW(`&K8MINXZkJ#@u0k|amlL7uU9`_HIHr)h91+qgEyX*<6+pdOZ?v&&&lg?MOgI#4V%xT!AyQ z3fjaaI5euT=lVoMV#l{|Yy@Ov-u{^fnR%-d_oF&}1_bUSrcQ{wEJFOEJ@>iKp?$0Z zUw`g7NTOYQX=#~JIBl79njKpxVNyFHgwCli+3v5y)olq%rUGxj4^@nQ7!1Shm09-O zN1bX^^nsZM#;kiAL(3#Go}P!Z&(+-Tv^z=L(=dI@bor#>VBl2r75trfA z=@YQBatk$AiCURrqb~nLJ0gaj%^UFDA5if9uyk!a-q zG9-De8W>$Nb;!YhX&?;!p^tu)#kb}E@iT~ugh@t!=Ydl&J*g*yK`Wt%;|xV?6IIuf0z~Xa$PMpe1w!A`vULTC*cf+-lKsd4o%h zRyE6G{EmDeEr!GuzLBX{%O%^e9t5|L4Pt-xtu>z(5|lj%uS(~$;=oO@B{)qfcP ze-Hz@9$|mFJ-(Uzk`52Wx1bcxfe*Dcnw{sknSwqUHwn%i@}n(Wf_EJEp{*R?@TknH zY>IZIPdu!~%tL4Y3N!7{*&pQZl0VF9GToHmjceDCVJ8`hlU@Az=bwjCu?X30hL0s} zlBRjjz(~xTayL_3dTG~_71+t6>OB=ibCZPVrYT{Ki+kjX`a-{E>%I=^{Qb5c#9VIf ztNCw_GeAJ@8coSYGM;j&KMU3f|KbGECw2 zmWO3HGLIUyDe^UGZ9Z-3*U-;3)V}ww*~#u`aQ)>nB-R8nb5f=2cx%dFWOXpB)_O&Z z`ox1LAUYCj5bAff)2wc%%4#I|P)N5*nNmUMK3Ol0KmOjGo(I=~2FlRUAW4A7ATK{v zu_PEuT2HB9^`-?|;si7Py?q!?!4`?plcpJa+79V9(*PDxV(N-y+Rl<~PGj4riK){z z8I@oxBw!{cS%O82hLRucfGVn|~!$^E>b(Jf*Rjd8yb#RU(M*cwqX3$<6x;8qQ^+XTOkJU{V>FS4B#7g?OMi>I=w1;* zCv>iBtTG1c%Iv5tV^`BaOx;1?yKN1d?^(VEiYi;F&ryS|0k3=e!qf)J(8H%5yHKd; z@{z>K-&wo0IgW$=SJ@2NB9|eGHikn-W;u+FB$>%+%ROQgZRzA8n5MXNRArdS9G6rT zV-YBGb{(|Erz*JkOE5j=XO-(7awM@{?2LU%!uw%6_ta(cSZ)VeYC;!#`fMT}GV(_! za**CB!J(**Dr$gq38naP6~-eneCvGyn8F3%T_+KttCqCip}U43s#|Y>uEgNl%df!J z))svEOJ9bS<~Y&)+VYj*9odmkOXdm2mQSJTry?P5E3(HE(jXGS++H1-TU^K=3( z1XZqkP7ce?+`sR*pFP+=^d1$C&I@?UIRtDfr8%|7(CR#*euQ19o9*1?^Jr;1Z@#}& z^%GU?lt||KizU#EDB8|rXgkj^FaUPm7a$`O4@AOn=81E)L^2Mot!~2d%~dGoEx)&^ zsqtSLorovpsr%kAb&-XAqJc7WJs|6(m?#NOcxPA%>V=&ggeufjt#qz+RcI(Cj~IH5 z*z4V}kh*P4Ct;|n-6oXYj{q>pMcM0b?G7F2SbAUZ*`DMRR{B+v{_({pCQcz{xLzewt?g+92TYyrfoS;XNQ0Q$ z`$T;)UD)3_;)eQGw=?x}9Ua;T3LiF*L7U9D38~YX9tm397x zkvZr!vqs)S0Eu)5nd^dW|IEYq2OFK+L;^emRI#gScT&9?$giAGKFjnjYj~WFTe%w4 z`!18(jt0umM~^+l>EG6V_h00~kz$a7=nI7sq>~xg+DyRJON($AQTo`#NUhD0GbbRI z%)<7qEo%qeFLFA_m8?4v55s0&AdUyR)-Eyu;^Q5 zCagX}6vlGY&sp0-eu*=<5hHIE=H-@|6IE8vL#pC~-}-|L$GN}s%ByftB$F*2Aqj=@ zpt%jcejRQ7ss#W02ii2~7sU=@;cu4o`eo*B$0VRXtwft+`bN-R@2PO-G2NcJ*v@;s z4rtS#hkneu#?b{AORA zUS;axImW48>#2wUb_e;K6Xr^VZ6spqet*eS!Ufo8+82fnW2aW+l0P+j=-QuE zZdA|Wo`p=x^7uP+bQY#y0-Rj8Q*+Z03Wr$jPAVLuRI%(7dAx6N1w_ctp7MoU6-vm| zNn0NY)_V;PkeT;0se0&RAk5rp+wY_v0D5oxy$z9CJ*c+u0QUeE_maWF!MS5`h$t2K z0vsHXDapwiN1t0MEBoPkN~y)qccno-j~4gT9hrT*A2d7Ok21<3!%t?d z>~S@Q-YfMo2@a}_oAw7imObjgeM+nA<=75wWTC@+AOTr_mQ~=S_30%XtydyuPPydS zZjawDu5yV2I5t&xP(O@Y^!Qu1M$H1UizfR+156_0x^Zvk?b_m?nN^S1QQyYw@SCSG z^gXwGU1z!^k!eFzKqb4QqY2o6Qc)o5kvQZPAv-5NbLx}?LIGy#lqk*d2jkM;RWuD} z3y|1OGI%9Ip!#wo984Lif64R*6R^*;FWE2VpZcrY{_2hG@rlul&#$tmqElMTa)oo- zrgkzlhXE(c);QYRW1~^41CB{ItYkB~9mYls9Z`BB?a@oQS*mxtSaoRQDRpYAeg$+N zhv?9UOR`IQ_a_+aVdhQ0xgAftYacK(CsKsL41FqKF?3gc7Xu`+n~}o|g4fFC#;*R){?+V4@1%EL3X_aRIcOQ;JuL+zLm-c3Ufn zS}vQ1oo!UPmn}XO3Ho1}o*n;EaCB@jIREe}>@)3;${i^>xuBQxu;LFzPRB-~EU{3= zII=I0YJFmIw3aDO!UcE!_z_5~Z^O+?ixwhNOSh_I#ew=FB?(5QrXtB>tyWLM6=YesR@=@d$8CD&0@1(@pL2JiI?sv#&+Y^SSqR@t+8#N@8}*?d%w@M z_T9ykX*y^9{ihV|t5+*f%t@B2-IPEWWi|mDC8+s+%`D7<;%{^uARn>SuX;12~F+7eGAQ!;tE(>w2kuljucLUdv*6Edo$nE{tdZAJUW&>?tM z4}_8zeSRf2w=naY%hy*P$>$1>7V-tYXu5c^p<8wcs=^kAay|+ZGviPxlp&43Q}SPv zZ0LyO1s80g@BsR)HhqO`wLspUx@$rjt&q9rzC5>YL>GJdb8}9& z-`(_4zrV$A(SXEt(ABaE&%?nH6=IO_r6yHBz0{k@JeZn*OQ>+8@VukbO>V*cBH*6d zi@Fc9_j3dEKK?!JyeE-qt7>;Wme$ukumm!#zPs$p^wf6u>RX!GT3w?Y=1mEn1j#=O zn*0DG(?9-?pGJgUg=!%SvlA6KGGAhCsG_)eAZ;X8;Z~O2t7>oVr~4RcJ?(ARrhOr8 zKrw5;)-q)#RlopphC{V^4iR_RG7ob$I7)DKc-ATdZW9$@$>)o39Uw$KsJy zUuZ0;#%3~bK(ucR9TzgZPP2OWg~L0BFy6R&`Nl(JGpB5EB+=Zwx(wS}JMh+bJX)*7 z7LG^YzQ-Pf^~E*V*-Gx}DG{;r-{gRRjQrY48bW>bByo^Wm*}k4akb@KARagmDU}}1bbGTFP_JblHO7!%y=L-eSll12oWH>%0 z!2=5(I_XE7(sEAs@Gu52p9Y0mYrFbs--}kF73!D0B*5XQ>2msZ@biU)h574IS=3T7k(i2~HnZ_YR}> zd_CBbTF!}n9O>F<4!bq2JO0Y~B2>%5O7V)IQJ57lkyjZ>z1IEw(Rm0&f?QRN04NdF zfw*~X1yadO&9j{-9*=IEyzkicYCd&y^6jw|A)Y!AyT$$?bg-EE)*t`hWzEpCvZCUq zWRRKrX(Nw!iJT8ONvz3X0Aza%hEWCN_pvlYwoucs9OO)tfJ9KR$9q{bK~hL6GFcTQ z^_q~x%i1=GMQso?2*IKL(>3*I{PmzB>*>-uHbPB~S%d&W^(f9Os;qX944vk4eY)A5 zJivGnYWp|=%^>GSjm)MAYj!@i9~y{2+bQKJc&B~2r#;dEuN%&s5|RayNTp6@N}-N{ zti(YM%v+4ye;75M5t%kJ*X?%+H?o_D*sFavc@z<;+e^iA&2}y;5)~h-24lgT5`*eN zF>|7QW#~ke`76nJ^|=!MY8SS)qXqx+BV;(T!!-0n-D@3289^S9hpP5 zM-if<5hxc*xFI@6n>&>7VB80a3~5P$k|AJeqW}R!>T_Of>D~6XI#l%0zQuy)X?_bA zWAWNoKg_&WO-8#mgJ9*|)j~dq`DwZRKTD>AiTf zjOa&3g;RjD+0~Lv_4-UZAst?X6l-BJb(d{h{O)!x%cA z+oix%*LIKX+~pW7+quM>8h!|w_y`2XKLnCG4!)6hf`!x-W<0d5Ew8}J%6WL<{CQYf zT!b%u@rzuIkSY-x2&PE0q*YY-^s{kz@(~jrIRoBFba*yyuBV5#du-<&*3eQOH4^x4 zUVp`4W^MvyF0Ftlpm0+*z+&DK158RJGc`ZmkR6W9#uqPKsj1o{(GdHEMdG82<0l_~ zS*;ciZoz?rVCdPX5e?~OpHD79(4Utj$<|AlocO+o44ZBiF?7E1Ca^P6I2LBlL1yTV zd$3bCowAE50&+zzLd1CI?@=HH8YDD+vUb@fq(ck$C867HQ zH#Zdvo!iLVL}qSQEZaFnVG$FjdgfG&#ThH9*vT|O%v{s0V^J%YLQ`8(2`HPUZf3_c z|AB@G>^nn0_S93P<1AhI&;R?X1QRzezH+tTg!9nDSiEryqVX_LAr~V0jlu$s-hTp? zuPj0?m9;X*5oL;2l9`bRRB@(Vy|n`qaSe{n;)E7vV=i#72)acZ_mir_emBg#TOV$Q z(QiMZuAdt9$;^9{u=`>bE&7;@8Ss{16}}NV*ou9Uuu^1_y^ZF3DqDp0gaR+zl;P00 z4CAp54BZ2Q7HSNHF9LzX?*l0~0sgsn;$oBoy|@LXrB6d?`O~mR6><=ByVWs$KHFvl z?P)ph=N{LZUXf?3HbRYq5?BBwe1ft^B};QC5DdI<`k~`b%OHJa z#((M(eDJ*}A^bf!DB5?1?vNozDAp_y3!I`4Xc1biN8cv|B_%E-z;g3}X;9AjB&M)X#xa z6OZYot((TOQHG$l1yP(Iqobo-T2|Er0cL>dru#~_T-`~r{TT+`8 z9K*FbfIw^(FU|*Y1Q&2M1irC{5Lg9JQy5?yXf|nrf_6a#)vT7Mu6OnCT}7hH_uEMW zct;6|(~nB<2uh18JG4otR#(t2F8s6jeI8ZiVJKHj*jTyAK1OS6YiJYC!?ml|pn&T1 zOP4M&V<*)*G5Su#`4n)h%CcI9t*rxBK^+)FA31zB z2|l% z2Gg+-m_IZRmFpFpbAwOX#5yNj6snY23K?h_C4Kr{FFfS&{Xf4bkfDS3=Rt@cnX?={ zf=ql4k@&k9k^82ez{TE=Kg(#-t3YyR2NKx=+`Og3Y*mI?Ie_CRwYH_VJAbdwco4{K zAgB*KQ-hYP7Y)Fkb9?u`?vxcyQsRud{p0Ur6?i1Eg;y`hjL_pT7Z)VD+p=9zKhL#;#e(U`}+c~9rWlwkdhfI8QY8;N8IfZ;F($L@X&DFXT<^ueFKlp;d z^xW~2%U~K=@jV~ix4P%;=)f4dIjQBumIAS8cq{0WCvPonB8RSW2Du7KfZLlpctd=( zTIqCyVxuvbJ35a{eGM|@lx06BBF0V+C+LR?PPmP9iIM&EnC0~@Zg^50ZL%p{dAE1!l&=a9WJR`sxbw%g-G&u5;!>E7ZrZ%m4Cb8a7gIWC_)(0qZ+O zNMwAFD@hPgrN(l=^+e1&j5bhz9Brbr$h^myfh&m2g&&bwbO9Hf5NsuOpj_7A%9X2J z1OAnlU&8Mt$fG*-T_h4)qsbWmEZcIRnugkw{U z!U&wqDWp;-2Cjrpa(I~%IYYX3Fhmq`83cj}3w4tnd~I!&Q?@RnTAiHQZmq2J6xqSx z3N@g*ftpbKm&pmZbVG(SCq?~;+cXB3WOih_UE9{3&+B|hZt9R+uR^)#V?QhkQzIu@ zBd^!wUO)1e=va*T5QVBag;>bffTFL`XbyI?Z;~Wu;v>-up>XguY`Bss6!*PUYAZT0 zhCcJ~U#Hb1fBs+p5b7b~i3=~i!Oj8{lU^-XA+eQ&a3shK-AS8Aw)DAUhajEEKqisi zW$5H6N4E5dD7LM@X0poO?z$cR)^CjG?eQdU(TDS=YnxK!*6cdHy?}4 z6~%63=pm@aCgAxO2jd+_Ok2}6X6l5>>9bzF-ij(33ZOeBWaw0;0M+G^XwA^+9Uz7t zIfRIO0a5s4pp2Zr4HtDez`r@Py>tPR$s~OKbD!r0{ga>kBu9({gCUsu$bInkv-g2g zTE{-~w@=6%05f-+0j=}7+w|*t5M91^YAW3JBXii996Ss%+QS2*?*_>?0cz~wS~waB zie*#}r!rZ%jB50YuU~{WE?#7n`sT()*LmoMIM&*(Qkc#nL%%6QItTr~qiv2I2s5|$ zb)(dV2CG+zp@$HRt5)1O3E+97CS4Ijw~B_vET?UoC`66!Zzi?tz%DByefa3?R|ApQ zYx3*^D}k7A-}AP&q61^-4#j3?Hw{g>8j3{Eo2E#hE$0zj2vw>fJ3cuIM~@%o2SN-z zY?oNwK-ESroq>GXN_=k?tb#2<3xfd?R8iHD)dbwyEW*SnN>$+&m(}j2J|Ofdn!oh3 zumTJ$iHvK3p{`BaeI6E9F@Qe2wx13cAuMMgs2Z#Ra$-2k=ckhKyTf^*W(&Lgpo1fov)d zOUsDJws+vt8y7id_{NRvY_?imMe|gl$m1f_J9#y)?ig@sGYlsX^#wZ(Zb0*?;j{T~ zFYW4o?wjG7p2yJ(lW3=E?>K&rP*6Y#ov`fT^ywR8Moy}9PS2{MW(GfR-dyJL7Ua-I z_V3qTy#P5>HEnHfAX-dAI-O>8-YYYA+G+M2C;PBr&;NW;ht>5GY$jw#Bn8CdGAM0) zI=iM^b(@5yQzDC6Qx_0nUJgN{w=f%;_T z1Eo7@Ec;BO{t86>MF=XSQ=@+j*z|jx!VlRhwi>T|kU>AxRSX^A@xZ$rn^9(ZfZCF9Is#EXXvFVYvK-0>Q zESRvK^}~EfhTuU|k-Zb=Q@;Z1zLJD<12r{)Ib`S);2U`o|DFXk@&Ge>3QKe1#*@h< zM&;+f`8+$deevn1`MJ}+L6B*O2h$v9;nn^mB2!T+qd_)L%pC>Ou-V>JbO#eT!%-5M z0%{zJSqaS+q(;Y$vb;HR5NXFy0~`njVSILyGd|W6soDvpL+x-9%q4wdW@-oDysS9( z)WK!1YN7*Y=#$TF-GsM}EgwHMcTO*Bm2W)vN=2(`p)8_rLQPjL-h|jl1ZL-_YPRsh z_Z^4$^cXz%sb`^xNQAS;k*G>~ODbbG5`|2u2*u3;M58K%aOEP~B!{u}D9JVc04^H0 zKGxHeZ<0toqi5(m7I)M~0hV^-sQbI8A@!vh*}WcLaT$E&bvS$9Q3y=<;H8&eVS89T znKs&HRXQ@qs?ESno1vR^$F)7D9f@&##t%Mx!@lFOAOw8?@3;>UH=^%o6jgYmvk;wq z5d4$pKt-Fl96y2!I-xNuEQSzK0nzqzfAPn#wz>wdzVZrtEK}TYmC<*#wmHn4h@Ep( zA8Qh5|K;oJV1DjJIPpOrjEzr%Sxz)M#|;2MyCMfE@7d?Ak6x3MwCt{*>k@7L?n1=4 zg%St<_`BII?w@!+5JQpumSdZcf@u3L!zyYe>6x$MGylfdzs~4;b#)a5H4U{emU)(# zx(AuEM)m$5mf%NWTPUPz)rQ~eiL_Z1bN$k52EG?EeE0hUFy$9}?m;icl%5K(fHy6Q zb4?pJG`RW#3c861GIKOt8RVs220gW_)gY(rBljPJsY5dm4u@*}W-~b!m=~|DaNc$z zMUk?H7G^(*DwG@k^#-H#xYO zbxv*`)tFp5QL(m>ummBWfVojB?tpVSgzEN?9~6HS7x+<-5QWR3nHn=EG74$dRgpJ- zDwRaF>L%Mp*KvV&b8d%7?M@6rLxe?M@CP18Go(hML@<;)T^V79PI=YI364G3Z8C74 zl0ZgbW*KDUq=iY~MviZT3b%A3GR(R;?tE`~yuH6tMTA>4`SXsXE^8)*@=*a6y-K3K z6;Lls!zu(;*8zn~QI^Awbtx`GjxZJf7^F{ z4ONgAzWLlM$5C@LTdrtNWe}x*ib6mPU8i&PX1(K;UJa{4o@p@bOpb=-MeeFo{&~Lj#2ZolQy(65*eg-j? zzWZ?1-eh$8w);onei(-rUl53b4JehZJj_m*nPIqJG}+f9Ai+4AdQQ(OaC%OGx1Uzv z#FUJRBR_k_29CbpR-=Ca?W1wDlRsps^>A@_9O=%#^b*@YKmF-XbKLOLpZ|iT_N;m{ z#aT6&eJqTKieN;)vy+7N4}LpLhfpg}`cquMTKMbqGq*e0&b?>=ns@iphZoy#Bgn zdJx;IEJ&Fja?^6e_D2FRHZuW_yz>dJtX5AKUb@82+a@5{l39T}fNmQ@Kl1(`zfPZ@__6n2E9Ue1m5bM{WE^Ox z+1}V;Y3R_ASvY)TuGZ$v6K6Th?FQP}iA=M##`{z_kwTwQScx77G&hOu={osQc$YR zOBXM(Q``CT=iy~U<}1r9kj-WrY~lS7XRSibfDdiy)Mvg@hVxgeuw60Wdk&cpR-v!C zy=Q+f%-rKUF{t7z+@yKj!h^Wc;`|gwNUC)I#8b@FgEQaDOk9obRx{CTpN7{iTwq%` zC48X>g)e{UOZ@vF!pw+tyFw-TSr~O%C)0G_zbs44%pW-EgUN9To_bP+L$dG0Z@DffB=!FUveRshK;f==~7idK6cO6d>0^(;qM z)fZqP%`rK`t=`%|gr2JHpPU*+b(gd~{f-~{<3c=+XZg2qyXm$u^x6P?fs~@@n>Ztq zsFK0)h$z|6bGbY-can%`aUxp=g|Nx834xGhPcLRI)uD;U3*9QQ%1;w*?j=McSy_WH z+AF2zt88YzJ#m`>Q$LKam(w+?vIf?156AX%(LJ>F$yEsAe6bLS+>)X58bK;JJjSn3 zp+8*YP}?&-q96m8;OL|TW4Moyy1zEREc7E}g&DaLi7iWgy0x{%Ht`$RufrNH z>Kp4DT>Z_f$Gj^d&s%A?%wsB(gK#1R)p?cG|E7LWc`tg5Ip6b#*T&{Py-buJAYf(Y zLnKaiaLGT8svAG3;nT?NR930$;Dcf&!_Sr++DKr_XLE4%>J`r5wzav%Ot+uM-VjpB zI}Fan!D!MBr|e`GcSunL`<29_5~wKb%}&bvZX8>XU^FJd1fueI6s)9OaM0A{26Y(_ zF>@-wQp}T3MG*rM_erV5p{hHs{j3R=RhhHF1%ttcQxhK|hOSi`H79{kFeAxIhM0M| zT)rbzP`90-KlGvRes=MV*QPJNbn!8KHe+~Ko=B&&kip3x3WZ<_?HNH-wW~e_;v+F` zGk0tjv`Q5g-^g3)k`hW;QWZq8VtKveD!YufkC!Bi)7w(yl@exI-zDDE}1YH_v0#MLcX{+%7jpgg4^+F1*T#$yze0k zkw0-b1@tc$iOn+SPyd(nUMu?E3v^&CL6cXJ^~fDb<lYqbaT`DtgE7Pgj-#ZF>`{*a}m)CT%#hd{*FO*?>MZ&*>9COa| zDvQEYz6g$@JQRsVt^=7jz~C3|tD8%d!7Tk8p!o}FNZ?$E^CG}lUBy1Zl^OH3UnwuzFI z2>Dr*ETSYv&L72!CA|jyJ^H-&r0#9^<@VD-rMTR8>SIx$sYDCbXh37z+9Fsn;&DXY zq)wkiq%szkVFVHQ3^H-re+W^^Sj5We*6q}V)H)P>SKx~;rMblKYp=b=NG;c=THQfg zj(xo2rP{|h$7NAKCL3T@KMEl;00HQe`eEGrHLvzzEJ7VaMy-Mzm_bb+B69x(r(~7= z(;y==mwe-pFW@tk@@Nmg!OVIQ%_+q~9U&JjF@cOd65Xi}SV(I4B! z?&L(U7<+d{PII1oK7xJ;M$kkwHj48cKPSf|WZn`ybjm{LC0kic*s2Q43r^#!o(7PSC2N$g6l*1(%H1 zbyK=ym^smHXXt0X_or@t{BM0QbLi;&dMcTcSC`gp#|?nQc9Q=NAd{vNb`BjsbBb^D zt6zV`${c5CR#JmH6<6EZw;!Uy-wO1R0W-LaT`tNz+i za{USv6D9b!|K>BWl^mRE+gZFR`oj%Fr_`NNRc5bba=Ieb@3!_GAR93_B)$wi(;%36 zzf4_p`R;NI-B^YaJY*F@nf@R%Z{OJ4*-kFWyCH^KD=SbeCg5{_@j2GS{K+5v5i@{9 zVjBiUG)@v0Xgw@d$~Dh*FGTY=5>{YtT7m~psb~|I;bGjUa&*6qgwR*sAmInq?E;?}+RlYW$Q+qN#cm{sr<_1xMy=&*Cn6t*)s+qQY$vAfP$&|5 z2{mAa_x#L%`5f=~+5ZH03f*>w&g73(#wVg*C{=G9ljZf3h9Smq!p;|{${J4MWMUd3 zkuV^NXIpwO6yOOxdvq2`c+B>#Ez1@{HjXmdLlp{V^KqTO#jP@^q+T8K^E`1>rG4jX z7khVkYG3!aXx`ULU!L2ycN%kjPPgCP^wGTEV;^o*?alOUs75bTOgM8m01D2lnGv+1 z`4O?8iaiz*?A#xPNhs`Yr=w-A$#=yYEKe3$vucSL^I0@B}ZB#cHp%KChQ1l0d zbh=>dbPQF^an9)H897usWfXz^R8=1u1|J+!U05Z(K2d2Y^+ zA7Do|E`$<4$NBP=$bFoWR}Ri{p^|(FRj}(zxNUJ=aSAoNdGjVRbV|LuhD^7@VQ0Pg zMC>AQvjKTqsaOed>R@GZ>+S`wDiY6)V}}($;0aGWq(B7c^pSar!a&>jh=tBaM+oe+ z>7-qlnQ+T)yQtbdyyIQd$+n!Ykwo`N%^vTv<@iSoVg&`KYvJ~EN$Rwt^@$4O+Oqp{tFcBp5u zROTw6n&b0eiX=8kPA(i?8JQTz2mUFz)98+1=%2VgYP|D!;HD}J>B#95SCiWbIkCBO z*7=>(9uzw8j&FIKtKL|}w_)YlGG~|5>BbjG`l{mlsc;6lqR)DmSC;b- zLbdym*$yQtx-H~xUjhLGa3q2L)$J`+?LFG1dKio7v;82((2OSP?`gGI$YMuRzsC=+Kd5N&=!%hOY|u zb>X#3tcn*Oco4{lXr^E9dOgtX+I!Th)OPjL-q8lQo)f~(n;!)Q(YWNFL{xr1e$H5S zay8C2b6t$EX5^b+{VFrouRr%3d#Yc0;|(r^L#p*Onlb3NUdod?^LN}|nmKI<7h5L>%Fs#>fk$U~cwIx_z z-GWMaHv$C#WzOeUQ+gruC0U*toIPcLbVo4skA9R3!59AI?|)}LJ{r&E(%FU}eR7V| zo6^Bjm_c+Th7wqTGy2pPJd(iZSlzP2>okk;Glz`+u9Qmec1ik9B>SH3TX6|;(8R9C zMf?W^if}}v5yjCb`r>RBd#1(XBSNFBtb!2p->TdqTtb=+tFP}Y%`Tv zy-tZ=C4F&=sbVZ!;`VH z0}A$3KQyDj(L*wvLxw&+VkL$V&5ZIMr&1p8W7S07pt7*eH-O^TC_Gg+8WdaP*&ZE@ zH?${{MmCe@IuG^v0no-?_4|F5TW>6_f8>|`aLCZR(eWSq;amChSAX-?tv`Lz=l2D5 zO*@8+{21L_V(LpbZgB|P(UXUH5>r0z@u_im@NMTHxt@R<7q8h~jQGDK+C6gk;!awk z>9sW4jqsUHrYhh^WVWZosz=nG1`Z~JpYfEix=N|ePSP~f_5grFM{tyZ_XJiNp?fRj^g+y(WNh7`J2ka1gnJ(Ch8zZ7;`OFb++t9A5VJ z$5c2xBf(=2Ne~VS-V{57At@*+35*a;z9oIWqu%`*oUu3d(=&PA zXtod$uHPW^3{a{>V@s>KjEqf>q5V7zb4TW26nO{{XH?9WP|co%ix;leWrY(g8&nnk)G3!)Wx0#0M`<|wNigQic%K&OcF*u8r!Kz)an*s(1buw6s%dINa}>U3$WwGq$yz_o9vHRl**m zCZXwi+;r(&^`QI_yr9N#?s*>N_{137Mz7zv=`raCp)DCEVlo_`QQ_eaW!@Zk@+K_gbs5-975tmB+$@v*y2Jc&$6fbi!Z#uiD1Y^ zJ_vHE^l9wWW;rxEDs?YJSuQEW@`;C3w2w>heIHQSQ~jjl&{%ivjA0sHc#qFRH1_AI zUBmarKHMkE>dkguPp>^&fz+lBsqGPb-$*-C;oKzpTE@!RZjuH=VJEmVZ#fG`?>_;4 z|E`NaWrX|Mm(N47P->|78I6TgQ`6%&)5|x$@bE8x;u74!bjKldBGsps%&LZZ638K{ zDBuFbaDof2;6HLypogxomk03EC%Yh}gjMXs`ZX1n^I%L%p=l6GF~|wUK%0nUG4w$Q zw7oF7RzG=RJo_z(_t5{rs@q+5KcHvhwXG9MM<#6A+%R(rl_LuKtfVmUu$5wVA|@ds zLo*ZZS7o%Jn^i<)0W>@5%+R|JtuYx*8SR552^Ty>uH?XX$I~8FtF4hE2RF*lCMl>w zAF&IfjN(@mR3sl;-wK4Xk)e|42gD!z%qP@__d&PKU=-`WoBW4T&j^i*u*iy<)wMhSJ-H(p`pyF%x%QT~ zO#bH!KmHTRNGxm?3&qE@s=iRPv&db%aD|iSpMB&${!R~Oa&8Kq{J?wQn_qYiU(y?( zQJ!RaFgv!&EEZxvxqK)Bn-vW%T+6}yQ~>Q!cFruXHleONIptrK-h<409Yd%6U5-&C%LX?ZLI&DJOXp;DJ2vHGrv80z58z@h;6rF9 zrA407&F<1Va;XhCd;h}_pB;hEf8klQ_jdNQR#k-;Hk6NU=ZVMjzZY#`e;@#}IE(fM+hmyLyoG-)IzWNM@4*uaE z`~g?CBL}xZki)1QM>eMr3Vnhnr#35-Wjtafd^vGgg10|PpA>c`SQu=)2fcft_xg@{ zO}W~xpS|B*UdtYVZujrRss_2F4ojDOh|p1pW449|q&5(_VgHrgg>mlKAvpfvNtl|O zW`8V)wl)*&-A;a5H8RB}wz&|DkA3lp@Bfi6DZbDeeBy`TPNqAOq5q}7^tyTe{73ZY z$XG_#tGBf3#?9|5^LXw@LfvNs+MRk-xA)V=OTYbS0uBm&_t3Aidp?G? z*kWTc5Yh}$0gUk|6?hS_Fe!syk?>PxBz9s(LL`o;OoA5G00scv_F9;XHX zy}e>(#lvlLV*|3t)URK=4w-Zsk~=#CDNSmjZ!0RHKJ6;?ZFUGTtEYHW=H=+#d)Nvl*_vr}oml}1%4cS$6`kx{e}Lg!=b%U)mGM$K=d)UBv;B@~IIWL4Qwg|r#eVuMM-zmIfB zGISw6hPslE8BhP;e}4@p{e|;i__DuPD5Ejl#Ay!7;`Lh)j)dTmx0E;*H-u_8QoqwS zyD-D5_d+HQ=|pPxiKX*a;g--SX9p{muwCAOSfC2=mnX>+*2oJ z?(&(4I+WMZa~f6ULiT|YIRSEL9{iK5AeH8Dn#ql@^3)Ph0ScTVLe;qDfya;dL zMo660>s||%bfQ{x0;^}MHPyOXqB%hV+F^WlB+&i92mG7^>)YP0FcP=hpRi+&34|4CZJ0@V&;{S3F|ij7GFmpwc=^O7*< zLZQGEs@x6J_6#Oz>iU%>X6z?UAF0_xq9bw6{u7^wPEho;cxW z8~Dtq4ACH>un`$%kcr1a5;OB~fEIhR!x$O|Gv?cYh^Rt1?6ZW_LU+eDD}2r1G}aYl zOcyS#z@c~+o_II{re3iMS9GEQ+>iF}m|zA@jGIclDxn2V{6Y*|3C@C0V~ETbID;Fd zUZwSym^azRmu@a{uKKmLHQ3(Xf~~D>wvqSB%pIG$Zl_(=4MrQS4$&L!v4 z$jq--A+w{h6P%?SK^u6cY}wE0(rj<`_}B<6oH_>a@sWnUC=(p{laRW-_ACVyDPt)% zebpBoc?KW)65J(pM>F(y{j*+X$-O=_M>?3ZQZE7M+oiK!$Fjj*AMoPzuaqR>K!fh0%y<*{Zy*Sc6>P`eZx< ziB=gTGe1aeL^~VXAeectszbZo(P@=)fIo54>8KP4k6iP;DJbaXy zxPR*1oO+eeIXS(NBbH>mabht?Y?(vT6b(dZNTyy z8l-pp_?!aRjgA`%Ta=fKW5_LSh>GAXhKzjS^s$BzH6k+KQWnzs;w#7{in1(SH6`_x zbKm!Op3UbV55M|{a5vB$&Cng1IDY>d_^xY-?dOi_rV+zC{s2kGDMH`)J2^5?HMa4I z(OR3M_Z{als}#mY_H&Iq{8ZB=A0BmGQWmn|1u!Nvsz^Zl-eW=^} zVoXiyx8^>38AsjUJq@Xk>k)&xo_-m1{ih3x24$RACcOU(-JWo5{wrYmmuy#Gn9HiD8>y?G#7E#&KO$m2iNLV z@<^vxaCP)7e)oYo_NY~=G`wIJM47`^S3q)m2bPwW5qa;hDxLDCFW$V#VPT6)OSSZ? z{S-uTilJyW5~okjG^y{V;O$1Cpv;&4;7OGWpPV@%a}~3xF&SbJidewEC#)nePQsVA zf~V)X*#hl~{@&4!rjT|`d%TWrs`mPRsU&J@Q-kegfwpr$ez#sGlLT4RFv&d_DK;>+y#;EuPQ zJ9Jkt^!wlYzFWE>w9DW8#)>Wk>P*ZBD71hOiHa-a4%x~xw`7%rnT?w^8N3-j{=0GjT;b!?ugtsdv2!2o!2YX1inaDojrZc;AyM zGxX{4evmk?aUrIx{hy1;@DG9^`5BzHqc$c(4|6XRSy(5N5;n& zK^D2KTdTF-NL6z2)vGXncm_tsVh{-W!SDBRT3C7^Pn|uD=(`Fpe)&AuNwcjItJ{cf z(Eg5wOGs5D$Y=^oq58doD1Kthg?ni$l_WrK(yZuk4maZfXq`l+Uv*lm@4fWlg zT-fObmO!S>7+m+)>HNLi%La8wYZd9)!v@;o0e%mTn9p zPA4PH=ZB_i@{WQDZ3};#GqtJl`xt@C;Uj1xw`z?`0n5iek7ffBzQ6hWXV^>ql~-PY zt<6o|$UaW#Qt6YckoCaKo5ReicKo?zCpQ~Z>YbQ5MJS+37Um{pMB)-W@c<=$LEv#r z23&ezY(!>(GULIARXj82p|DL{bg zpaXEh7NXc#oEdrpab_7Rp{MgqER#(UA9AURwt2S&JBEmR|7dt`J<%94;<6{Dpyh8u zOpF*~siH$7W5T?O3tI#RPn>?$hYWoL-gLA?!4v!%;se@T+lH@v@f+~yTONc%3v;zF zorRM}x$Whb-#}YS8FtpUxe}XML?$nntY?pCULab3BT)h$N}l7R21}fNTm9bfUbaK# zt*DLd{J;~x^wXwA9|vta-_u9kch7jS-*F7$c{FQN`g|^v;x#T8eC+r!MBGJYh)!8n zO*iZeSXEXlJGtEJ5$N{TCVcwO{uF{wYH;@L0vbXC-B7*FmNL%?M5@!@!fJH?)Vnz0 ziyA-8c5+GfArlqIPz5}H{$2kwdS}|D zNy(A6QmO6ddr&*F{VbA%l`r7LVING63V6$dDjYv7@kahOTnL2=qF5g74fmrL>Su23 zm+gEIYmJ9Bv;NarD=AW`h|}U5pQ0QJ3Y5wL9;q-<#hxmHNltAQt6>1wa`J9};#=Ov zpY^o1vI#3oYp}Y!4%tkuPFWzHl@(w1!S{aT2pczN2Lz`7ugQ9~L8ulB}xLKg~L-6RAx~NGNDB`A| z1u2I1Mcodm0;{Grqfl#WRa>2iP--fZ;oJQKb%YtZ z6M9BvNe$tLsu*KoqKbkvCAA@M^o@-zE`)MxWrah}R#&YoU0#`ZrAU|yoJW~ z8X~Vdq9r*=dV;pqEgqIZMTR~tHL(}iR*{Q5IbQ|-f1oB)qgb)3ph z6|TN<19rAk@ZiIzAwCk_ZTr4=!Pc!!MCb`t(^n}g5EXDKR@kXRpiQw#Ssf5XJa?_g zj!f^q-_Q12*$t%b1%-D*du~oUC|hl>5_P9O+U;}Mhw$JFFi3xdmiNNzb-3xbWBcy5 zbB9d506xhN51yWc)pZG8xsbDKYwO^KiIh?0zPPdjOKU+`*$To$T!Cmv>N0MI;~<3& zgA!Q)b^I|<&@S#9e}Z$V3)vE=X&hAaXj?Z#0TZrX4sk9 zG_6`o{NgnRofiM`5tWhmx4q5Bsds4BLGFY~F6%(gkB!TlKe zc|WXCG`^#~2nWrY0B2u^zFzqfsoDjsErxc-L2Gypd2f+a?Uq+NNm%FJ`4|MlAx;nO zP@zzQ#O4m%xV8dU-nhBju}SJJNX{NTb`zg};;A41=bwYSnC>cu?hwADYkIXBQWdp= zYQ(A&T0%sOJ(taMvVd~g&sC;`WM#;rDm!FTr{B_BcD${XHNu)4^yVTwq0}=JfRZT~ zoL4&yIdg{++)$qQ@tA2VlXDySN|EqFRm{S;%}mJ5(2vepp@m#9rJul; zCT8xQ2H?2X++Q!$i=f}KO>gHXWKI^6TpHKqvhB@InfVMfnd((W=B6zZ`hx*>Rt(^$ zKVS)ztdYWZfdE``C&S^5&0`ZhnanFXGIY4h>8@nx-}7_-?oWT|BactSCdWQfE|k<< zI#v5^eRT`}zXdaMlZ;TNXD0B4l-c`zY+@81eCt`1@>U_e-INv<)%7rgZ!cw#lYEdz zz02#%Rfyxue)fpZ8%k?KgY>{2m>u3D@)Rxh_4JbW(nnpJJsIIVUPs?!=(}yxf-Uy^ z;pyB$Xb>{iKsB;8J9#Hk70VO*!J~ed8j;{zAN9eBSqWywq_+1{j#vp_0%#YP5t*yw zkFr`_QbM(3C{tUhXca;s1pe92e3sSg+gn>ONMgGjg>O%H|62G6r%#_$klnBN+P$Zk$foyIS8TK~h ziv?I-T!JEgQUVxq#ACI()>~eVS_$M@;S<}wP9bNU_{Cl3Hcsh`pOoN*tZIkR4o*ya zW?X^Mm=%6TDOqD-0Lcp)?_q8XMyu93iA>LQyI<@U=dYGcR-A6%5>P2hcC0yAxfdwR z5Z7d*Y~2UNP8dVUV?Kl?x-x$_Xd^mF)-Y7Bk(#wx7J8*t*(0#{@6p^A_k9n-s}}(~~=(7pus;1(Z+~S+%oSl5Kb_O4Yn1 zc>fbtS=PV&Ek2&B^mn`SD6!KZ1tuYM^rIlu2&l1BwciMJ7xQ_zeq$LfU%CwE&!2}S zw2@!CcCF^6-VZsPHRip_4~pVs?_(`&vH;+TM8mDw|=O!k5=j^RYT}@}aLBKKIB9{Mid|FVJ1f z(2>jxKCf6Lz9Y>oyqeFZ(}i>jF@`yb4>?Mz6>@&NwY<&``_z5MY7Ha!HXk{C3{ktx z44uN+D4~T}MQL9%K~M+;%~+f$Wn4H`QMFSQCfXY{4rTN2S2j79)G~>T=T6}EQ;!SM z9(DWeqCqUE10wPV8jT3lTuE?hPC*$Jk&Q-$U?iBvZFWpy+wh4wnYB#>V!EXrC3QL# zL^0(U>D$?vt%!)5oZC`p=2}}_<*aRl&Pmly$zZCLO0SntL)%(iK@?J%Iu*@oWlP&I zb4R;Cf;SbqA>>Ut(~sdbhk}&BO<^;`!i<1`U+iCWNNq4pj&QEX+$%hIJ#BM;eN#X7 zd^f>?yQFI-ZySpeBvw&DT9!G)k;2nR?PR3NR;)P<2~jyQ@0laBFg7&-;b@p`=+0oN z@X8J%bBZ^oG_Up`lK6Ad9}2Ci0spq47p|kscoXgsx@#G_u#zDc|LkM`WM}&1i3>}w zzE~)v)1$bP;?tv=Z7W$phOVNXt%0G(qY#XQID{d&WqG~x@l{)WM+}`NMmPW!TtwCi zBq5qG5!8XIOfp07!5%aSX?&o}e4xnlVESmu%x}ka43e3P+W)-uS9dI_ibtaoOrd)6 z)V#t`8g!(1es=1& zFJ|6r0hV6oXSX@wg<9NOH$=>w)a@IKGAzGAj&M{R5TC1=vl)8Dc6}18W+!#~^uio0 zoH}YV^j&nmy|n|WoeXbv<4EHFu7{$LwaCawx|GY@c;Dau*(-35(A|vCneq_ciB;3j z8mMf<2XtRCpDXLtUDe9wdIEW~1X~*k@KIUS(I}8bjUN2W;aTwc{c!cwH(&!9f5nbX zH1cJxXDEeA%-BtYGbzo0%LyG0;qR(~NZl{*W`u(F@13XcHPPWWw|#hN)2@Bp_n!Dw z&&3!qHUCoWA@%H(Sx>0?%Y})ZU zz|$BUvYtDx*NDv5t^;hXC}`G^tqgFKAuf@(5`yWrW(C*hQM8#KK6M19=cgeQ3fAfr zl-L)_gv%GNL#5K_zk#UUkYq{ID%G!W79<1#>|E2}K-1G(HKZX8mPoCB?zkO)+vl9rOIu)6v+%XAEW&mgIP`1~ z#2zcP#4iRH%5WUtyiz16vu5J{qdqu3FW~Lx6bK>`4+UB=@FCq%RR3H|D;h1c1F(8c zKt3a(z()+-%B5iDEB3^(#C{0{R7xN-cXS@2u~cQh2j6mzZR+3n{Bw{_q(CQ*jfmXXOoIrhAPA-7Rz-w=GpoZ^PKUP~MfH2o z3jOIhiHrxd)K=BruS(79V%INvZP~sq)u@+yG0-u9r{~f3n4bC&b?y34Uwb)s$F{b2 zd6`1ZBzWllw?eKQ?1`Z>^0HITT8UqFv({OQv%BjJ1!PXMdhV1}!R!NX^Fbtp=7qzO z{k!EC;PdUG_lE0oL7kAN`vfw4bYp)WpT}NRyGKoe^9*}^KWfJ|J{wP_gSzvXF2+FK z?3Z5vw3{oC*iOj+P|l2%5~;_e{gV{th7$Y~g#oIow>ObwYk8l7)G_cEtI*6Kpk zu(vG<#HIMe%yTE6e9zY_<=l06=0C%|M)wRupZ~tUU6`B%8R-O2Z%#n?2&P~|*u zT33UMuGny#;xBb$S1Pbg1C%(15``&BBMal)1hm!{$_?fq2`xJ)l$9jammi&5$dvI+ za1YWwH~s(Ymp}FdzWhgD{Gq8t? zZme*Th^K%5v;3W+Ee~bh`OvWueyClQ7sBj^dci(TNimbP%6SGZ&rQc4+3A6Pv^*g#D^nT})+xt?7&>dRV z-vb&1;fMe6r=T4*mnJP$tOd1dCxCHFR#7C&F8<&#ADlfY*O}I+P zd`*TM7k#^p3aA~elu%2mTRB36RhQ%BxzjK*J_6_7{#bLbaQ^GBLNbwt>sOa{(K&my zi}T@FY-j4ou_a*|pZ(F_`s`o8JxccsLU%}3^s1pNc}Z0?WY$%^suk_Y7T}D5hzu(D zu#1HfhqKkZB5A^)&Q2pWyls!E6w8)c&@?TSj__Pi@dlje8rgAx%;f6Qs1;4=KK>5h_nqpre|!FD^Su?dV&*-L!}Gb@(BLxX z?UGg@k9G;lC329op*Jnk>;*^b?e29b2)tZCWZ0GF|dY|{y6Eb&uj0dE%=b}Z6V?6cW;kRzbbU@~{-;^k?jDP*# zj6ktig0;2PniHE-2!%q-ysFZj_wN1$AA6yH|5E|Bg}?u;GAqJrVRkL%X;-^!hq>Jm zp?5>(9sBoy%xnA1rt@`2=54!ko}r6(X-_8|(7h+kSlyUgp36Q?tDxrR62j+A30{0! zwO0ZKL^Y3F0rc$(m^r=HVD9)lhZ;ZiJ?{r{XqM^{?BBe$4BJ~txOm|z*Ez2zNr-J< zAn;YgG{5jKp1t{R;U1@Z4xu|F3|Ik)lkQL9*I4~;TpPJmhJ3C7>0}0ip&;jacPKUz zgL1jT`GBeT12K1QhpHb@MFdi*a{XzV=_R!HR8jsb*!eU0iOJ&g?*8wo>3Hes0@+z5$N<~F-Ds~a@VC5aWwfsH)T z$7AGFibC4n3Yoj@qa!ME(MK;@35SdVf4uGSW3afq4$pn_#af+l_k_&aFQFP8 z?cod7_P)2sY!@GkN$zr}3m3?|BXzNzdwCu$zV}lw$@I|J6Eg4CNe5)^sh_&<-FitA zBTq^2@-wQPB!+66S3uGWU}Vdn?^GN|0tm;#oDuHvr=DbHF4avGV&t3a+i>;LO;}yo zXfZZ%UQq+r-uZX_`EQ}$kzj5@zjo?l7} zNE_MBseZa_t8ys8|LnpXWDvn8H&Teybt@MzSz{_X2ug8D_8vdoLIK+a6MV?f(?u(M zCgeLno9IAL#=(==^T%CEEt#X2=f970#r3`IK8E?RDrA%Hn7B{1lG#v6R?01Jd8JES z*=>4)s=CP#3kh~8ZN%#A*nmT_$)KjZbAGUPLYmrrKs zjLgyYjcQJ_V${;Q5(A%{pW$5Xa`!I0iZ+c^-{h;qo$M(a_TinxgM@pa<%C3-TIB4aLf6Ey^ zqwo*B6$R$7fZ2(<3D*V@?$OBfb1xk9>X8PP5w6wu?q_doJAil8Z2Io1=>VBIZB%5X zQWEg`*A*ya1u|yA<{V*`!7P=)*e=<%&8cjicz@=zMwL`aPmSqmmbX}HiP)GqO}fY zonuICL(*OZCr-H(h4INzX6mw{aEQc%Z+iqbSJvSAg)3~Qp^Y*ZnTS9npPe!;5(Juy zR}&gU{U{Jnh#aEyh~I+>zNIR#4dZjs4-8^a8ZfgHE*95)SG9XlRku67rv<)#Wi~y{ ziMIQ__OYj(duA8XFGE}|!J$b7vIQLyX&p_JR>8N+7^P#}!8Cgv`lq zK07YBD2%6TuOm-RaP6q&`vsoIvfHMM6I@Gbymqr6kMex{rqBQWlRt7RyS-Y- z?QG2pP6)Hh(9@|bOMK~6hC?HWp%c+UrJ}lL{`euT>AZO9hMky3w~;#jS*o%JJn9oU z>C9H%fHF#+(Hi5NP(xv3v!JfzNa!1vZ?Y(PNhFdC8hJ-~I97k^^vqfrGWM`bv7 z(#O@^-gV9j2bJaF1bDMk1(`W9^{rbH?5sNGLlxNseOXcHersgNdBBxY6b357$PV({^&-UiE87GdS;65G_d zkW0q$ij$mrl&G>VAdi1-y$W-23ICQ+4R0c9H@c#&ew=FB?(5QrXtB>tyN<{9f;>eF zWZus>ZU_2pMoax5r$K8a2GZ7q3A8YM&%6DQEvm@SeQ;z(f+N!s$BX-X66aN?SD`u4 zlAE!#QnmMNNv=cCUf!>+s`j4W(cYcb`gupq7X5jqmiM6hlOZNfX#DES3al^6klaM1 zUd6_G1<|?AskODwwh18s< zT~^c!XfsD0fc)!{qHe;Qklr*5{cryAZ!Z7a?|)A~4Mz%EwMz9RlPD*S)*qA2=0M~G zOM#9zB{6nF?PSNH&mETGj{vW3Xj3PXA?-dsA;V-?fx7yG`%f zrr)l%^Nw?{z3seG6p&3zaN~juH(pbqTmZCv)1b-}JPyWs%5p3&)ZTa)nH+(`r;otg zk$IR~m}mbbO3Ur2)Sv$BR}rP_aQ%wq-`1GGNL<1$HYbjr{*~$bAHO~=$6kBtV;|Gt zO-OE{Kkq5}*+2Y7LIN{SCG?=lL(55yQ7Dvnvtn&+#}~;$>QtsLh|;6dT*$>);S9st zz$)ZIsbQ%KYt<0oy*T6@N&@a~y4%Npn~A*FgMIz1aw{_bMd_@%w_AGjD(2 zJyqY_E4?XS!wVn(xUV`n8T#{||MBlH7qUNKnEF|qar5=ZknMb8YK*scz4r+#sX<-3 z!Ohi8&NlbVpMHUp&}ikV^#k2eRR(D^1P}}Wr@k^d4H7&!tD+iSf)nE!9%8mf4on^q zx`6JeuIamIbxgMz;pRN8P*{iSsh6rmr~d2OG<>@K&Dr0>_&XnCwzZqEht(Fg- zrB0K}u9^;7x79|Zsw^R5w?f%Ft=#))b8od!cx*c`>ZL!ojIUGMfs*N=-#(vfKiA$c zhW4sj&$KW1v`6Y^EIqUxj8>xVd30jtZs|5X4?^S=S5AoB@?y6%p8N-;2DTA-y*m*j za@^=smK)u<$VN^!b6S5Z4p^#@N$T_xNTP_E(!8qrin#BdF1q5D?xff8!0G9a|K^Mj zVCGBz@t6K`F}3pqP6|po)8Hr4uO&*aw2*)=)(cRKd-#UfxF+d=NlY<^5AtyTAG~HlmA`f48EpNC7%86mF1hr{CKg z<0gTOYlPn882WD8_BXT3SetIRaKT7>xpp_ty$57oJER?Q?sneVK9{!h7O1an|1J@9 zON8zPnYZb`rQN?}+inQm12cCqkK8?*z0X5S^?26^Dw5 zd^-y!g{F}=yJ4M-nE2UuJ`B-#3{IcBf6u8XEG@Z{fvgf35k+;74 zd6Xrd{^5W5?=QiS-aKCJtw@7P5i#~oI6k&0Npif9O3a{`$>D6ZV{m3tj5-x>SzXzL zXeXdsaS`r*6mK_4f3CZ*_g!XVnaU1 zCe((RcOx&y?l<)@mVL9s9`wE3)5mQ@=It2yfzg1@+t;-Zg1RvCc5U`BRrwvx>SS2UDmHYG*QsG-P?>JP5sxi3|!r7R4I=}pbh-~Z9ShejPp|K2bD z^A}O=o_hVye=kzbXJ>IX))+d4uu&#CnrIaJcyqU)Pe{E?-XR7EN|K-{miisrE$?U$2?%Z%kaUQt71%fGq{?&Ic94k2Gu9ZS;4u&~ z2h-m`$J8SYgi%1>)HD8U!EjukZ(r`e+1EYo^&Q<89ZZ|S6!Si0f9$V3N-2!8+w0eH3I>oB?=tjKg*TeBnN(x!K2?Q4Cvz=bJV)H@7kiV)cnVXqzo(NyNN$DU@_B%j%lLiU z0IgzL>0A-47>O*U#{{!vS{dN%bgq;-`^4E(Fg-uR`PrRJoW(*3*3nFP3z7M?%QtyV z<*JrVB+K$kLYA*bCgy)l_9>S>eQ~J`*MD=<5TV!6-~KOuut=Z3`u*?B>RPo}Oea^l zEoUvxP3W8F| zq1s7DmHbw^0u{p#N+<+A$w0JT>Bt8LN(XkLA>DN}oEvur-9gWxkn=%$CkX3HCCF^+ zynb2ohGwmEIlBa^zAK>+DkpV20w%++O|KG30 z<8l2bfBzH=X)g^KdJEDG@hg>LF{%bb|H3r1pjO^nfsZC26`*+W`PVoe{jKkOnD-M? zSN$qX%}(*}qf_Is_{MeEL=whaeEcZ&13?^knLPlOFR$*y11KF?)>yaoNj#XeH zq=5=e3GKR}ntJLe^@FEAdT!s;rk3on-!b$$j(*y4n>JxzUOMaN{GIynaxc3fb1!3P z_-=Y0M@J{PZta`GsCx1{6CL{X)V8sW>1Hs!AoKcjwCJnTn7WOl@o%&C|4h;kx30x; z(-EN;AfGnan_cJ>{%u%EWAvs%E6Bu2&3^R$qf@~%SZ(O(vrBbEc z1yV+t;{3x;{yRnWWgmb1@e9UR(=Nw=tH`b z=uVs%{Rjj@x+96!pmI@Wrk>u;Lwaj>Nt7(FH>->^n-zB@6ta^OI;U9kJ;+?sA(zdg zmNUoYtJ@KpGIyx=hd%O`uOV`(l4BeUsVxl|dK-G+C;zX6@yZwfUuzd%yf3wKOE*nz z#x#sG&Bv{;Zt>@r{^B`KLi4tFJ<8uHO)O2~Fsk5HWccL$-dxbd*v{b-K>K^KObN09 zVo}JU%BoPTKt8WR(C3GT519}Rm=KeSod@j39_NPoK#whx$n=Al4!UipK0G0v4mM9$ z?V-C?!p#`KL%%KhFu`M+PTdXSnKu9Jv8~z5oNhO6&wVv%*#xfuY$db}h>u?Z$e+LgwXN6-j-e6>@-6n)0$=di^>x@|VwFgbpLU zj6H51dF!|QR%mP{{nihUUWXxdr6EJ_Ko5WC_iYxE>%rXm+On?6iVg;)7*uhx)$SXo zghe9N5&fOd7uhk+7f?YG5=h9f$w`g?d~__%b$xTG3_HE1T#L4vvi(P>|1kXAy(0h3#1)%lp)nDE6R zm+JPtZD1ht$}j{o^n6B!3a&r7lmx|`4%L!wU#bCSRpr8{t0xwGiP zg$usQ>gvRo{=@(09qHA@A2kf^6f)wL9vLKw&K{bEv566Q+dCg+8@l7oNwmF@KvjJi zp8e$0P%0FmnB7I)kQj@GWP<%*DB{vgV5c)^llJh zJNs(~gzm|9?q&?_e(z)a9sB5JJ8$UI^gcGX%&6tqp!FEKwX6TR#qaLYh=MBy)XKBn zwe7sswRW?ex9H1sdmV22>o7OWPQ_Q8wjJM5chM1ho=>Ow>g?`#9o9#BCj!O1fM@WdtMDGU!_sMCE4frb@U@k(u$)cRvB66QgkG_`;rZUqo9uG4oen ze4}QvY(a>`#r3Jv4}Rw4JHGYxcxCJ9cl`9PbWu+Z$)O=a??PYs%2&)sPMjzUvyxU- z-=#_w5N=n;QDq*37Wa=r+6uWMJI#e7Aqd-rTj*s`eb(WllVhmPs=!)#)yn@)DtP*V z(Yj7?Y#CojKu6g~eZe-e@cfsxPu^3Qx{KDGT_hF*OeGUM@9$5PGo$>}jTb^kHm$kC0^ zxQUL}>4WW~Arkinn3Zw$gp1&)W3*70tT zdDHJbA=~=nMDs4Qb=wvwtSdqn;BE{6&>f|=_}$GhUeI>KP45AjyFJGBvol-&-sPUQ zjXQ63o>u*PD8SN|1$scxd*)z=wx-wX0B~tLH`{0eMB_2dZAG_twDUabh|FuhHQr@6 z8i)1eF*F;>@P&_88E90f4h17~N@HCD$Y;UK7*>qAO@zvcsekKV`VdF^%pRVFX1aEH z5w=h}dHLcEc7%i0!{t(_BXbL1d*B1#{anE)zw-V6;OAFhNS0hNk;S8R80gLg_o~C`UEb!;v7X&gsRWiBE6k;ZsMUfD_z6 zTRK%~D;2B?fE3y$D7ze*>;*TF!1PlR8XdNiMJV_H!XgNMS%rF1qe;+sU9c8y=DQZMv8FoF7%-GOXS}lwP(_ zx#^^FB{Yp@Ldu;1MYC39g+g;Fq1NoNL#TOF*=}BMUbOlx;#PodTn7`|$u`IwO32K2 zB%g0F5E*&RAC6oD$y^Cn;sqFzXBskem-Ns>50TNQ^4zCB^;|Frum9=K{ljs53r=fB z^(jQC4fj#QiJMHM*#R!Gm4b&KI|G5hEC|J_nNGRei5`3RTOfs#o$TtlRF3l*gYENX zW{NebTA-@l^!Yen@{N@&3JEHd#RyCWOAzsCIR8-q=;Vd%2Hka|7Jalu=B=8$MW7zX zQ2XxnI^6WzvHbv}U(rk#*^)A!Ej?}E%-P*-H`W(@tj zqp-IRH_sup6~^@{46i?zhH}whfWh{1O5=)Zc1Wgi<%5Qb8!`{-DF zPrp0J#FrOWVd=&yCy!|}+#(@!V&)Hj_h0!euANuD{m1{0D=?&7eoq^4p6hmX!dC=_H{Ix%(`?cU7>J0bRCC=tRLth|&3x`;W7|JQ|BIV|R#zfqd3NLg8uG$pMaR=AfA?-~JDW$h=<~GV~tl(RVMTSI?J}(S@VGYgVe^#PW@KWWp*+ zs1GzBOKA}kjDM0E~w zW!pI}!!^|*9At;OOePOEbs3U*8IH}3LJ;liqk4jodb4(T5A~#K_NHoY)qW6T@Z7fF zb2m5Yq$2g$RsV~6yO6pL&700`dT3i~A-eb5c@Q4IyX?!gs(trps|(TF81{y#HN79M z?nN7M$F(5TMb$1SJDU$mB6GU}gygS_%U3*NY}92=Mr_1n~(!#8G07 zi6pAuU8>&uVMs%|y)=AwL-IhRYA=_=kVbR%@>R6vrBTb5DcPRvIGv0N>()1=;ga6x4 z4=bk)h=vTkPulv@m$*dG{qO(opUtk_9AA0$W&Ea(8@hh3`B;asKl6oe@aNm#{W!;} z&mEqw9Wy#Uii|!6Blt-n9xpxnJYa2HK9PnNVqnWE56*|*cwh26CWRe(~q2i_*k6NxXN~-E9aca zM2dmM7e4bG1CP{BibHZ+k6*lumzzEE*t`CFcyw$dUI{!6LmDUz8G4`e)W<%?8D3s~ z`csLEU-)wn7ha}PYAr)9oB}R|yyY%RYWQlkF>eAPc-nl3*h6?c*{B-AK}Z!w?~|rm zX0;PTNBl1K;6gi|p(r`X`B6ffS^5-GOZa^VxY5d4v z$I1T2M^OzbT**w`&i+RK2|FqWwSg3wLt4aU(y<@f3i*PSBunq088pyRE}#^c7|%rJ z4`<%-6F)svvk#btug3t%G(RrC^2NyPH-7uypT70_D?epu+G*3!Pj_lV@#)7-F2K~x zIGjFny!H|~R4SHP0{-mpev&H`C06Td1`7)yh_DYt#1Cd9OhN87)DRhog5M{><7daf zZx&%vU$dIIL1}H!fN0gO8MQdO-Jn#@W9YMO$9~(}G4~+!j>oq6+s*k~j;T{yZ|Pn6 zC%3lqwqt9L2pgVv(=iE@5sZc)7!Ja_zVj&t6yuY7 z^JgvHxW&0Po_qF1D3!{VfY6Sp1ga3LM<09FC+5yQx-v}Xx_>l8=mRDhf|@TF&B={`Lglvf@1o<^&P}}>?1lELU)SdwkjkT% z>*&PH4}|W3Yaa-8Vdm}H>|v~8_qRUA&=-luKMY;MWk5nEZX!cBICn)YeJh{VutL%( zc??xaGj>Npnn9uvGV}nhH?kt{Y6tCuG+o1fbp{%=@lR&EYq1NhC~{6nQl_d^O1JQnytAWVMtm;c}2kxy)WM6XsK!8hknr#2x}YmK0t>cr_IaPq#R zoPDXj>>xRvP$s!=eEzFY$Q9t$wUynM)Lv{vP_@#=PKNnVf_IlRJFYtzG>SLxZP$#a-QOw0ZM2?ZEWe>$Ex+QsR>YgN<-}l)ArFJ zf1h+Z3+ZH*lVr6?l|Fv?d_++J!jTxFwiQM0XKL=X1A(cD5T<0FU9}X?daxxmHN}EGPe4&=FFTvKW z4Y>O1WzZ@b$ACISzHszprRf;QuA5OiJdR#o4v+K0sbdkC9uL5{wu%hC*rj-b*{s=X z_3#AriMERDnBB?*=;%aGcnh?x2$ zF$Ffo8Cz+tTW;1xlQB?0P2S-XhdCte?30f&SRjV(5SjKWl?vQiUWW@WUFMY5g+f>J z_bRSC7e?k6zWm5{|IjmLRlD@Qzw?tDFr= zCrkPC4Mf!BGJ3qZ4cXKwyWGm+8l&~2__9$lnsG$t4pE%?`1Axbe%0@X0&d`sC@zLOY*Tnb?G zR+*E zuhI8k`GI#IB1L$)m|a9Q79sT(3|;4KWoZpoS2iGkOqguz^$cCL8G3wd1SaODQ98fQ zvFPPug&kHL+q%iw<%pr@aKCapimttpvi*z(^rOuTqt?-4hT)r<&!{r~y2B{|VLt z2AgV_Q!IG_8F~T{`RlJ-K^49RrBbQWpsu5u-cbF4oEnXN{e%DL|NN6;5i(DH_`?|( z(t**Cp&uYgruZ`%!Ite5@1GdF}ENGj+0uE2s)Pa%|qx z0CRB{d@)f)Hh=68GxwFLWhmtfaPy5D{DNzg$c9YoMO4RENNP`m2>L(-R4`Q^iqkS| zttKJu&!Qxc_H;>x(ggJ#DOS zGXuZy@+B(*2Zev5P3B2T<4Q3$!O^iTT$A!pE&aC8jGc+-)XrM;{Lp58z%*p&2T1?$ z_rJ`=2mb3%{ME;VFyqPP8>{$+j^g{;f}!*OYh?$g=O#J*;=-{xHW+gJIihbxQaGy| zZ6u-Rb9q?3xr#43A?>QQmQ_twyMacwFM}OoQB3FXHgc3Jph8SD7ARqYGc8 z-T&m%Pr#54o`wwlHjpe=|BOBlJ@$@55%p$?#Vf?4$8h~T)~*eOi%^xeOganESeTR0 z&{6TdEtX)&KnO=N=73?5$*4^ zfPej~*TC{DqKE6~OV!>$jp=Be&z`1fleVk=S!pH;*LnnQ zUH75TEy1lTX)ef=+S06=1tXjT#*83P9rb&hn{?dv%QhM z+>f7DNUU{o%gkrM<%`#$jKaW`i#It;wi6@AmY4AKxsgLhUQq(UQnix*4OI+d%x^ah z8TxIYANjRUEYas5{nE!)H{ex(rK?F{n!!#hLJk=&Nz=sC$xcpTBn>HH0r*8FqT&gp zA|r2hQoYxRRtioiVOXBbv{u6*V863y zh@kHb+NbAWnE3vhA;@L@kV~U^Y-JO)ay_H9;>(3m1(VEcsD3x?TrVP&W9dLBT>9I;@$_XF(ru^Vl5iX8Pd@gs z(8vP|;q5mrKCtxi*B(x;EPan@YR62&INGj_qaq82LohZThoi^mVRCvLrlu!Ytwv

JUCEPPmIbJ|Z)B2+ z#YExo6xV_Qe}09%;a!zcb&FD4BDWsey6K~v?c9yc)6I2td%HSadpGpjp?}d}e{IpO z>-Wyr-U^|6K2O8GF1GU)ZB4h=0npvYqr==VyLq(NJ%^rb=XD6(gaB&ECn25k!P-&; z)~+TXvt6|9c zjqS;E{pzKgT)RA-%&>~RTGcuY_%aT8bNc>spBNKc$6qJmU@9Ll*xgN1F<&<_oCGE0#?tq3y0>s$fVeE^_h^ ztPg2O`#>ftO{s2qrR;}NUgA9LrM$+1xs$DpqE450@=bu;O znil-zzxt`~C>L@cDP=P;y;?zixcNB#Jld&k7@0PuX?*mp55eeI97e`sd(`pt;*ta0 zjW@2rP2AGkDNazcy9ii+NI`5zB@*KiFcoCp0oz6|fW7KTP*^y#zzfAA^Evjc^=B7b z4{Ts4wM`r7a9qniy4k~BAoOlyt3R$E%|bhb?&AC{5xSduR@>kD+Fc=Yx96)v(9OSf zEWqORIsjbS&doNOfHnxduFtlQ!o@t�)Y~1+HH{1i54puD-C!(J7VEZuqF+P*P;z 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 + + + + + + diff --git a/assets/uco/logo/lg_dialog_logo.svg b/assets/uco/logo/lg_dialog_logo.svg new file mode 100644 index 0000000..53c412f --- /dev/null +++ b/assets/uco/logo/lg_dialog_logo.svg @@ -0,0 +1,1184 @@ + + + + + + + diff --git a/assets/uco/logo/lg_lunch_icon.svg b/assets/uco/logo/lg_lunch_icon.svg new file mode 100644 index 0000000..8fbe6c6 --- /dev/null +++ b/assets/uco/logo/lg_lunch_icon.svg @@ -0,0 +1,2720 @@ + + + + + + + diff --git a/assets/uco/logo/lg_mfsys.png b/assets/uco/logo/lg_mfsys.png new file mode 100644 index 0000000000000000000000000000000000000000..02b25b4c18d1f2c313fafdb16fb5c2819421639f GIT binary patch literal 13300 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 z + + + + + + diff --git a/assets/uco/logo/shopping-cart.png b/assets/uco/logo/shopping-cart.png new file mode 100644 index 0000000000000000000000000000000000000000..fad6fd429c3e37a73f3966c59290a7a0f3c5a063 GIT binary patch literal 13735 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 literal 0 HcmV?d00001 diff --git a/assets/uco/logo/uc-logo.png b/assets/uco/logo/uc-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..99993ae18bb0310902059d1252ad2126de77598e GIT binary patch literal 154588 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

^;z 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

JUCEPPmIbJ|Z)B2+ z#YExo6xV_Qe}09%;a!zcb&FD4BDWsey6K~v?c9yc)6I2td%HSadpGpjp?}d}e{IpO z>-Wyr-U^|6K2O8GF1GU)ZB4h=0npvYqr==VyLq(NJ%^rb=XD6(gaB&ECn25k!P-&; z)~+TXvt6|9c zjqS;E{pzKgT)RA-%&>~RTGcuY_%aT8bNc>spBNKc$6qJmU@9Ll*xgN1F<&<_oCGE0#?tq3y0>s$fVeE^_h^ ztPg2O`#>ftO{s2qrR;}NUgA9LrM$+1xs$DpqE450@=bu;O znil-zzxt`~C>L@cDP=P;y;?zixcNB#Jld&k7@0PuX?*mp55eeI97e`sd(`pt;*ta0 zjW@2rP2AGkDNazcy9ii+NI`5zB@*KiFcoCp0oz6|fW7KTP*^y#zzfAA^Evjc^=B7b z4{Ts4wM`r7a9qniy4k~BAoOlyt3R$E%|bhb?&AC{5xSduR@>kD+Fc=Yx96)v(9OSf zEWqORIsjbS&doNOfHnxduFtlQ!o@t�)Y~1+HH{1i54puD-C!(J7VEZuqF+P*P;z znKTRC`lf@_cRS{UQ7E+E_s9bRLZ3ZgL&_~q>{%k-{riF&W8p zk<^Wv)Kwq-Qg1pCvF8u3jm^Q|(|)L*>li4tVCHVdut$g>L0iK2)sMVchGbIUJ1Zc) zmBaU{Y{ios`fkcrDx^aGEwryxi;U|t&NlO{oJExIK=JIw?4@G>tAlCG7_bZP2!7v<>gC|Lt9z}UwE?? zre-ZfLc#w0$jnh?FL0ySb*nt9b(9}%bUsw;-T&Be2q_gf8cTwx7Cju?sux)t$Bg(5trjOWs*ZO_+~ z5w6>_a?a48321I)wmqMKHe+as_(S+Y`eAwbIBLyQIRDudM$VZ;-8(~$Zd9nOjJEP> z1&keJ=oLFTOx+EaP(Y8PMsDWF3>-SX0EbQ-!Pir%RZVk<829qxDrb9p>G{`LXdnR4 zg-Un<&*C{WejOSQVdG-DISm z;)O-nrB{Jt*admd8u)(ub&H|=UMiNQJP}Ks6#Ql&>3n&*Q zSY65B`z90X35bqZW;Q2v zD+vkIZ(=*i=zL{qoj=*%#^_v(Ntm3Az2XaoQO6HkU`VgvbzIT2+48psgF|F~2h*Lj z#0{wh{f~e2qd$Oe>7h$s{PXX?hZQib!Y;0eyx%Fy+&jMIac1VRcy!M(VD9pB8Ak-3GSUadxQJDZcjGzHq( z6kG?Qoe(>Du2Mfn0lQN4QQ$ zn$kGvx(vBo2+H{SWRnIW^D1Og>yX;2Kp~^m@~(3c6%wHHlzScDuaahYt!uj{3WNi! zaho|hhk~<$>h;6?-UiX+)$F;R&lm8$t-`I9buO;5wVq(xxl5w_7~1IE!pkVwl<>{| zimpq;`sH^K4H^0!PCxW-e)DzueENU8AnBDQVLnxDptReWN>*_ zLhF>7u7X;5Liy=L1_F@~BK9yWoSufTF9@M<4iu{9#`bkv#aK`MGDA1W+*8{YzxUdQ zm-b%z?bb&pMC+!zex8Zw^4(?IzL|NS_h3(37k!xWI8;!*p2|)@daDF$*E5jWNo5_{3 zWadJq-T|r83!O*ie*MZ4hpDVAuffdR6pW6>Ioz#2pEF7QRFnO|Cm!Zl_hcdksdXyP zy3Jv3Wkl@`FV=Hbb~&h|IE}0b`8ni`oad^f%11li;>9J-R<#+iD!9(h9_G*KaS0T? z0IHTkgi=MM(!oh*Ajr4Ak5>9pH|;#^cXMo?*EJA^>oyH;U7N0saBZm(?TY5MJqs;O zPH=9=vPW=mes3SPUWzAqX-%bz3D_6Ro^-y@(R8W6-dUSGl zGpVd8g`m+pMA0SX-8o4pTn+d*^el?+=**#MRYgzf0&nAN>bg_MglD z>4(4bn5If+=u0V=K~`x}uy{v?PM)rm4T?}ZN$!C_fGf3;jlG_s6Eg?gf=B0BWfvVA zK?W>P(l4+I9=Z2!za<-GRIA9uC6HuFd_kV@c9~Z4rY%|}7t>TRjzZ@q4zmh=6z%a) zO@nF{ZL~ft%=D(CK?rEKmFT^ZK^Ji}AcY~7@#A|Y!QvZNIF`JSt_#z4yxNQ^Gj)8q z7@3>7x)?P3LsBHpzdk-Y0TZ)RFo%e|xx8tuTf=&{Q^_o=*(t^x<$Q2O0&sw0Rq+LO z{Gm|c^iv=C>hZ_FCH2r#Pp!j{?n=7rU#T}E{pR2J8v#v8%%UA`O7@3OCvIMTqL@y+ z#n5yGUvLSZD#fb>TD2wSO<^sONSLMlX+!}5Ts%&kUfAPc;}mTmrcBk_5?ecHQ_sQD zr5mW)%R^?zDRpczx}h*Pj#=k$Hx)Nz+SoUq5dZe^F+o)KODG@&{SpL&6m}DVkx@Uy zNATQo9zrq-0C}{tQ)*eaYTK5MPn|sLn-IF_;)UPoEpel2cco5u?*vynr0Ez>No2ZQ zdqdytka?^A+n#%G*jKmbYr4LU76`rLnD$=DUWDGl2~MbJACEz~id!WPI~zJ=QwD4= zlWMz)$k^a!g-pSAEUj4KXF3YOWE-d44kbIgTiH=_0h_;ksNJG;&WBDO=6Ley`56e~ zyGSXRo8!tWwy=Et>Jl^W_0=sFzDd1K8Z@Je7rP09YDZiTjZIvP&!4!cS1T`;)0;Ow z^wMX2 zml-r|6xv2)Rc!Oak?K71;>JW1|qiOk~8A7kYDf9jfKJcb>rqqKyhMc7vjH ztep}C+9|wHTKVGz3icm#}q3NkWzzZ`{-O7=&=NPb9n01d_cCL%k54}oTS~swlF>NiILVzkdlI6t2;BeR33ixk zP9I6+ELxXey~Iv%uYC1I_K>Fxa(jTLWT%vkTCwXe65&rX5OPjjJ2n^#qpC3ghwnQC zA!PE$r^}#974W4l+aAG9z@Z~LZi9Gh##?}{_Tzrgcc)`IA@go+o!zaFb2m*uL%&^+ zd5bahltiWtLKhtnwCUwKx}|q*wXZ&`tfBF4f2J)|>gofaX)>y_Cs2i6hQ-%6A&0_n zE}3p_g58$*i^yk@X&Ydm?VP>UD|-i}AoC_>efG(7;KRSqJbo4#xY%PO=P^+1IKFdl zympPz`3v88)heP=>5}PfmpDm`tf-aH$motQ9DCtiKlV?4A9tspc>hP!Fr<5ih6w#0 zA{5e-$SRYH>PO{Y)u(B;J38`8w|!J`!Jwiqc~q(Un3+?d2Z@n7k*HhzD0M6$1Ip`8 z=!8(Xt{KeStr{<8EvF1S^%8T}ETj%}45<<83&t2$LJU&x)A@2aWah}w4UH(>>_NXlr?>1W4Cg~J4E(FQbQg=tw9j=@e4MVZRc&z*8!Qg>BsbP z9bO8sw6vX5jRFNtJ)=0`M$yzg4Z7in>ldq_p$X~oa~GL`7wR3&Y<0TOOP0qvg@;lO z_LOcha&7NL%J}Zke4aTx4YAP}Jn)utEHG0=#64rOtE#Q8Y@$j(1D6n)ldYUXNIh_J z>+&gmtGaXgy&w6EZkVe-{ICE0AHk6BSsEhrdyw?9o)rqYkHZBtsRw1%cM2C8S=Xuo ze8UN?2fFoPdB*D;)9O#8*pV$13bI#xAmq1@hS)_PilRaoRrQ3hwfQQm-)Sos3bowP z7P7JX*KH(ICd4Dy{zpk|IHt`;?xt-Qq{UP(%dqX!5V2RGpjJRdB&C=UP-UIbyDI6} zgceyl5suMH9qBBz-WJ7up;pY?ZPUKQaI<^AZu%EpzVAELIl}Gvqs@1_TC^$AD(1^A6k^ip1yGW z5R6ZZ!0}T@I5|yomMS6#L8Nw4kVaeMjn}U*LtaO;!M4DLB2D({NBoW zZM$d^+VtxlOk77JZo#%CQ2?ME+wyE+(1$IONedmDtcB zy_tl}CeGQ71Ur11O=cW&Y$G92Xaz6}RckBS8Qq!(Zrj46V^J8H7=`)c3ot%44&%to ziODxtLUV{b)mK+GU~4l0*Do(|h^dPrDoqy&ujBbw{gGH&Qq}6oZ~e$G9e?n#ttY1nNg-S7NR?B6-FsvlexE4)8*Lh$vLdc-{ zk5X1r*jotE#uP13_;)n6Tc*`1{^Ixhxd6=Ek$EVg4KNT6Ti*5SmPc-mRG1Xn!|AaE z+XzL)E(l{F$RMOn#bD^u_LQgaHv`rCq{=U(vX-}Rj>38r$c3!bvQb}z4-NUloSDwA z8XWg4A?o7rA+t+u3AYT}O&Y za6VSGGUReqoSO#ZGYDx>6IIL?cs^P}sjcCuI*DJZR_W3zB6gamoF_(DsNKFWLf-Ul zj7*NRT|AB^E7DqxjE{0i8dpPXx*%fOR4|1SK2e(HjkPUK4CCZtcTFbbu;+{~99fb5 z{#C;;F9;p-abILp4=Dv0(wl;Y2>ne$pZ?Du8#7D3C*SzOC*PV{S$Z2T78Kq_+vE82 zsF%K+WHfJi`y-qM?!@UMKvPMQ+E1sn&46Ef?nMr{S-fV`Ulf?*7j$rvJC z1(q(MI=!O7+U1*^_$6PT_@&m^wvQWSa6HyYovtVC42dl~)&-fLaPH3?on>VH(36j` zv)jb1km%tt24*kZbX{f3)n{QOyOlV&?7}H}CL%ZKkV!o7>nzog4*9e4vX63W^ex ziZX8GosOs*)#8=%4kGgu&RGHJ?F##Nl=9>?ZWTwd!ZCCZZ7PmC!08_)t&wA%u)2N&^+JT+~N0NWpRxKTe6w!h9{?U8qt!h z_)2OZl*JeBWt{gfOM$>5UPl7T(6eMPq`Q}f2>ne;zxfY-=tDx1A6kClD{rY3@?&6? zW$o%L*GzadKYQ zlkFMLnp7Vm_5h`)Rq$^WnLKXnOsDLDZ6s8XvtAI#G%_;*j)!4t%mBa7gg|+f znYhTWT8p=CNBQ+)J9lGOu0xo6j_vX$y0V>j8k<|&c`FTo+w*ns4d{rdJ!wB2zYB$T zn7&!u697$~MOC^2$sHdu?gDN_*txaIrkOGdj$GZWo=hwJk(s$sVbwaNFgEfP4y`l_ z_Nff9XADmC#q7c?#K+=r+0#)k;WZtj8dW8`=G4vjZW6J~K zSSmVwXf-r4`s`yr@OQtmQYxjs>$|>dsA7MU(h#A)Nhxfq=W`Og7M?ux#YnY80jYlt z7pr(`<>r03`XcNxPrK=d7OGsPfXJiFb(eiUA7`G6kH%mGH!1={-zgWhqmm~itttu% z0x>QIbLi+Hwi%{&(p(T`!G~a+n)w1A-P(7eQMs zkK>@)*5pV}Ikjm~Pp(?%-R~3ZNFN^$aUqP+sngs|Y&5{;`e2Z<*OoyQw9psuRJeAc z+MbKZ(Bj_-g?3c6dq=OLlM1|RWBZ&Q#dgn(yzRN&soM9PpCvaE(qfiJx*S5ScL0HN z0FkU2rAfhgc2t3kywXdW<(*zN zEc>|a#Ll*HoBunSrr1~v0ytM^j?UveiR1i^^PHwKrU5ed*lPFMHP}Kc*~qDe0%c~T z`JE%Lb)3KSu6QPLc*D^LN5-~LQRecbiK;cdutX)EIbO2}MAu1JnP zv=EMskKp&c>PK4qNKH>0*!klrdsaS|hwP43VpT{II}z0w3@^B*?bl|jCuN&y*s6Eo zvyi%J($to$;uYm8+f2)LIax|AOKo&HhzuQ7@1s%n2~ed7B7T!(0c7wcWGtncwt&Oo zx;fMhX#nJ?E2xs09~pXx)#`>BWrkicC8(mgCs!ylLr*4(P%dh)vz)aP8|^ilFf(^d zDjX+np>WQxPLH%EqqUy&G^c5vQeATLS|6PpgR#kRPIS}>ky~MCmY_>j3pdvjmdd@_ zn`sB%ryU$-$rlK&ONyF#@O|HV4H3cSvx9pupo#T}g6YpsGWnnRU zN?xOo$GpmQ+c_K#)$rsoFSDIfuuYVk;Bk_$x>B(nWx@-iIe{u)MaSbj?)a!5KLw1C z=@zQsha55oa=b&6rG`wuO315f+2*?;^loZ==z!2go4@ybZ!Mg;a)NW!KQyYs+aYtX zlDJsW3MjzI zZhvZ)z-3zDWysk9sNMjDN)~l1??Ksd&alVh%pcPlFwMnKEXea>`mp8TcKFnBp34(c zmV+Cq+GQJ!v&VYfb&^9H&09(YLmI2~wM`amDW8K?=*YImyG{-xE@Stbaxj!fp+cX3 zk z@LCHmGY6WKYFhdn%0plp*7G*(+y|^$-yK8ip;?8297IkG zozfZ;0}s_zA#6uZbwa9oM(LADz0OEo_vGwWcU`82_o{@ms)#CmEjBruj!z%S{?&i^ zt5$-TPd))d8d5zC5&DqY(w9H}Ym<5BM&=URO7xYOEiXlG6pcrrzY>EXL2$+`30#)NWA@!m4*m?NNq_}6;0AbSu&+8s*tx(eU7WC5zPR$E@m1&7Ej1*;Z!9v=)U3oGXYUFs?k}5!TVT7e8~*Gf(8myd6)AV zSLh=~&P<$`vHh>1;7RSn+#L*|Zqq4%VrzfM>(NQOTC15NYS%<}*O^C@Po2I~wn6e# zr;2{$lu0?&35~bQ;AUOB$)56r!rAE#wK|lbhS0c!%=@I0kmUj*@jS(8Ql(+Mk11h5 z0fyCthvbrm2z^Md>Cb=l7tSG9I&|SvAODV0J~vm%=Oct~O)KQBXCmfFHp!`(35X$M zK6dgjBlyYbv09b4ZlrPix(UlSmRV3(xqO2ik~RssqYabmw|BE$N;ZNgUP=jVX!FUI z4c@1+N}cWR0n8OM>dq$*-rZ`;p8d!;h`IQYiO49lkSRe8l4@7wePqiIL?f)h2uA!C zx(`VlGw<`6peoiTNrsgir-o>2Mq#jHt)RvT&02DCVD@H@*I~rYeyEu-1XQZTge6pY z3(jX=Dwym9UdUA~4N1NTdW9HsiSH{3PZd-#(=#Yjwlxy0YzIVF_F~8J(6msu(5n`M z)=-O4wM;i=S!3qSYIBY@6P>LZ!b0N2q{pX6S%rS=!Bfn*=Z_s`uk=8R(!i~VGaI77 zNhq9hFHj6Qd9HKbg#H;hQ4t6Fj6WRRI`Q`ReOWW~%Rl_D{=*kxNJH{SLxesg*CY$0 zSOqzO3+WX^>^r`2^eD2nK&g=15f%zYjzR9_6!zwgochib=0j;Poyty9BIMr=oXCp*5jkPUT5_i3-)2mYRT4jaKCfGedG9a6j$ChBpm8h`7y$5yI2^x-5njIr<>b8FceKOOw z3!xASw|(AfGD^LI!uG4+2n#aX@TTB=AtdgD_*m3(aEyc*r4uu6m(@_W=LD5XrRP<` zYo*V0D#v#5ESd^PtHf&ezT70tEJ{_H8VIED0*YwLdIg7+HifySO1`0beMmjg5TOsL zXZpQg_-8+qPi}{=Kl>Nog$zpI0*ppfa}H)DipJQi|p+gSYKJ^n(KLTS|YD$C+Ucb1zOajcw!2ED`TA?FM9e!VS^Lh5Q>*< z^ef3uW9XOIx7uc49M)%RH>~ch^O0a+Sqp?MR|s2p0V_iqSSn<`WW!=$rp?Hlt#5Mr zu(>chDVkOy7h>3ynT=65-T#u6C*8ENt=73#aQXizhf(*`wh%u}9L*dZK*pW&hw@}V!5qRnAU*ZRB0 zaHM)wI9UDF(7v#cuVJ01W)3%M7t0J^*F>GNz((K9sG+8&ukl-Rm$BEr*Q4kUXk2A?sRE1V=QA%5Nx z7eC?sXuj~FP(`ugflvrP(LRp*DCBI9bDtd}Uc~uD+8ScwG}ma$$}Xy4N+Zodb4bR4h}$9Y|l2uPJ*M@ zwciP8D>l=1#xGg2w#klXqQTbPN}WFts%giaL@c(B+o=0)c>-F@obHKX3p={?S-Vda zo1xoX)Ew3v^S&GOO<|0Rl`kM14YAW?oDvmL-t@U?-cKItBv9!!)f! z8W;@``j7@f*VLPtX|eF4P?akPxn2rQPL9gH@R*iMtsz>U%qO!YyrMVR!_7L+a|gkjyZu_sUNrXK+`1MT5tYFSxaXXm%F zle1vpBtC}%NjW?=xfL24zjo@~A9@bW3fJHN<3D{JhBTyoq#;5d(!P*?;ell0_1E(i z#r(J~gf9?|k0ELiq4DWg5#cI3H!r^hS6m4ZlZ<>~4wvd#=!2Z_p;a!QD#6xz!uE_; zxuh#O($N-<1YvY6jtm}c@pi$OPK<)o`*f_IioGCnAQeC7udi5f?u61QOpZLDDF&TX z_GE+C5b@C`9ZP9zEiZA)W4c_{tQ_;2W}{%UE)A*kY1_W*?aIxOT5X4Iw*IZ9tRdPT z(+7+}JlM@a30~G6 zxI{IIVzY;?D1LuAI5Pe_X4xp^Q)}z0KawkJ<$O3eQ-mQ6X`gAx(1)}ygtkG77^aQO zO5M0|<5nV(kgojUZ(S~BQ=#PI)f1+bNd>LPX5Th;XMv{0o2XDL#DXf_P=FVF=eTe< zWXEIM`ri)3`RD;^p>pJuwR=)##jL6&Bu`Ftg?mU$wK2_I=P(LUBf&#M6*hee zgL<~ZpM=?(;hJs!zU|a#&v(k@5;L|`;(lhzLA=-G#6}F97&bYpg`yF5W{cwHBy{nL zzUzseDXG-Uwu2j~*vTGFrAoQZxTX)3f$u%PAjh{PBJxEg7%D&Voj-aRh1cQ}ANtT5 zzQye$l4~pq0nXD7&^=mBz4r2A9Lvk#44`;yoVsk2UFRVb63y!WEBBOBSc$>c$Zo8rGS} z+>F6ubULA9{7FVtdic$V7=j z5mO`vO%8Z07#JEz@Vrzx~f&*bu@BApFr^{UaFCkZuPJo#KXc$I#1v@CQ?x zEXQ8?%_gY+{tZbMhNx zXu(iVq4sZTax$)2DBFOo^=UCYc+Va*At(WyN-u^D#xQ9|QR z8rFTj0<>WWM{9&SBDILmO~;3n#V4u#|Jys4-Zri)j^D?;_z)$Tq9w}>>ZDMrKy{45 zX^_I+c+nOuPy=0f*KIf5_XFfB-s62<4t<;>iB zd(O;IVuCht5Luz*^8@Tl&Ws3B1a#(q&bjBG4ArObMWyf+?LdyHof_8RsW_Q*06~01 zNTCxG%^yGbz^~TJS6Vxpvj3Lb0d*fo!) zGFW#<^^Ph0kyUKgAeK!z%TxQP{C)IXFDzrfu9JIG!TL7Vxkr2VarQX|;=v%wg8e8p zj^5@;lJ^RPgD`7e!#(_3f47rPM}uER&u1@Q+VH2Q``^F(&PQIgrhfMOKdffgaegc= zEClf~A%#v%G{0O}NLQ2Ip63O9P*WaHb&WIq#6x>B*DXO9?1GA0OjOulR!fs;4>TQm zkv7;#Ve_ta+z!QAl&z@NBR|TNI2wB3iZy8r+@qRv)=-AEXUQ`U?p)2wtg#Hw9X^Ni zGV3DG-O>ab8#=>S(TFyFXr%c07vAI1V#l_nj~?5jc`=#l#+r5Bfscc9vI(tOx46lM zvanHKLW<9IVa#H(;Ev6H3QcBkU>q9JV1^?}3hU9l8$Bu9@lFy9-r3eaA*>@ECB2{v zU&xM>?)_ASgJBqksj*ETvO@_sn`Mip^^>)?fFQmKQs~5~GQg6m;wyhw$Q*3mwAQ*_PSA_!xn9;#}*QHcuYJDkjiL0Lt)8pr8sqt`th@YO7y zJ8lB?@b3IuZ{H89)7uxXyo(Bb>&9Iqb00Ti;a@m*RGYVjiOQiFi#?hccc{^eYcPmoz&}*vi9Vcvp1oI8;iDUX zNffY_9pJujDP)4?@qT4$N4SpS!dZp)tfNkI&vG_ohBdX6SU+z<0ieqW;*>)Qoj6mh zudOZYH=mYTpWnaMeYP|EY~%hrL)9n~XRWKt23HW&tC(maeb7O7%dvUf=bDeaIp_hFr%($j!19{YO(nIUw>athtbsT!_R&Q z#bP&!!s=Dt^CsDo z60Z!T(1|n8ty{MYd;k4-BM3g{Rr45>_&v_GW8yS3(UzX?c)sh;ytZ^1`_Mq)%_l0H zNt8Ml_uA)THJCD~cA)->U1uxoCGLACSPC`pPcdY}Z`=B%a@VU&b-hw~&k4#s;riQL z@+j>M)^$3JJKLKBBbZ6kRQcSEJ?Rcr>L_n>H$Mc%o z%f05-Y}9UD>^}R?`LNTP@9aEXjQiagohF{afS#*(3g|Bn1%H-4X4u*$xDBSJTb0>H zYie%(X}Lbvu3fnFFqoblEM9oyfm5v}OYgl$&1?iwKmnZ~UVyc=HK);Nh}Pf!vYe=P z^L#{;pZb}SQmbuF&seS_&6C34WofB1o4d_g-#I1#NE4h zU6AGO&fb%0liE_)?$s?zWv{urz)T`lyIoI)%8PpK8LgsV81|-Bw^K`pLwMY+VV!>b z^(LiJZ`6P`ehdvuWDpG9Ql%eMs(rUy>$*Xpg4#@5x_(lbTiAu$7Clv~@1yGW>*w1R zYTxDZxlS8i>&A^6iV*~HtdK${h-2dF)vIP>V?$Tk)A4|Hm=$qPV%=S92Sm7lbbJi| z95~T2)&`(ZOCZlH5HVf&@d_&V(Q65GeqpA>q~n1QMq^V4|1-rLxcn-csd_s$=#>|; zxpyS@~%`iD?GDE`>YZGC4q(NDG*7iA$ zN`)1t#2O=7@F}#lqN}YyGuqHi(;)=&w9#zRTy%nX36Mf3hzaE0+S*L4wbWs|VO1|s z;h+{r{ZgWmQW6gx2&9;%mypKh+NRRL%1z?n3PBa_BP<8S4>t(Kwrj`JnI}ExS_p0( z0qJppcM47dms;kyaNZh6I>vF!p<6D+Zcu5#QaNhN+$;J$k=Duo71khk>b!L3=Uz00RquFDEIk;SPJ+ zf#gqWN2QVf9 zo&TiO)4DiQYFmF^yBFbnyU6&aXZcwpi$Ox$7{CF`h%B|f5885V#^f^ z6a9Z<@q@W8f%KHHS$GT*MEc7LV{o7}zmR$KkePr!9YO-<;GZf$&nddhtp^~Go6X6Q zbW7OlzQ4y|q6ZlW|6las6#Vka8JXeK0cMbYAGt0}BjgVl~`;+v!#%OuaN z3}Gck;ly=l+Jy2A(a;CR#QWyQ(+)|YyxHRAVuRv%2l)b-Xo(^^7#TBJH~#*{CelXi zi}weB5dVu{sX_NY;$GgR1?e~UDFa~GUzBpBLpM1oR4ERz9{JuAHA7GYeA76w!8BQ5 zNbEYwbjq(4!cn$3RnU_j4k6pbIhBA<> zNKXFjuy)MWs$4&wF}q&12jcA9=vMkd{-!ph9E zK1t?SMSElqeM8}x<@Ja*tQw&KMs;C4zDRf*6#Sx@-Lw#~s6qd~&(;4>+FEP%_K>CZ zCZ@{Dyy6vJrBVWAj2$+$@i*rDjQ9)LHB8{eoWShnDF~vy4BVWbS zmKTd}8QtdS&PqYj8xSG`m1+WKN<(_g{d=rwr*=(vdL+p`1IazrCLL=c;bH+s+wOK6 z`xx585i;h$m;3x+xuNU_C4VX_5Zqw*e-R5mi1lyfQ=8Y<{Oml`4y6rb{_mnxV)GuI zdtaa8kONTv2Bwmd_bqKA|5%3s=P~BbFmA^Ix7ops+niJRjNr()5Joyi!{xkKP!>#p zkh^#)|L>EekjY$i+0+pm{|OT*aa{nayuxsuVwoF0a=Z*1QDiF3qkTjy+mS6DF1Y8q z`iHHXXHP8P|0bwZZ2gxu-@z$2K7uJeTw#-be-4B5wM;17g6tS4|Cj<4G+@deBsNgs z__tjo5(6D~mK$>_5h+g$s>2*sFEut2i2OM`l}-W<&`KFE6PXzim!P^w6w0#K;G7{G zYl#3F|4fNL%|P}zBu4I;P43(<)z2k|U!OLTV8#elkU>t*F13)3Aes~slrJBPHBv(l z8B@~W>O&8pfkx$!$etMnpv6ZZ#~<8C>OHsG@ObutXX1#ngrH{X?B_j5bRgP*|GUf) zhOYzLpV>=jigzLkhx^GwrFh4dUs}!OgK44gR0!U%kVqxtAB_45G&`x}Inu18G=-6j zx`oVJmZQ#@wG5*Cp|Mu-KN)+%M*nDPJqrrck^ha;_L>;|^?Tqn`Z7He5P0*m}{uqBGNPCCD`_+z5jQjF53@%$AE zR<~rfqBJ={Z|d!CYK~?df*}>(u6P*s%mK)3C9%JBn}L9il?{&y3X-O%za~}9F59N3 z0qc-gl`vWtRt404;y{P&no!+LPnBDSJ4ugz;K)r%WmG7aMqll17O75M5+;j;6h5m6NzEL&tT)NA)E;@P9u`@Wwav?7vY`$=E3gd$uSr?&)jLpb56mv>x-30d5xZ1_z7) z2Rj_ye>h6+a8|1DT6Jb}8>|eA@^ILrDUYOzC4$gMA3xzG66Dvm$EJQ{*>vHrU;R@3 zo|_s6fw{$7%NuL)FA8kUN9UBj%Kr!9`!48qktlX$nziR;&(AHO?rSo%d1u3$D$4l9 z0C1ZCn?8NvH)7ZrLMl@yJf3Y$oQ1K>(dHHDF}ZnWVLzg{!TO0rC%1RKN| zmsKgb%mL(+T2O;TS`yxleFyA8((70}J*hCWkhE8SlorWTsbhu^sU4_ql4@RN9B)$X zDpNv6OzwM5FEj>sv=+ zq-;WjxO)tLf3#(X|2ensyPyKXni;>x-ws$nO-llUXjujEY9^cX^9CaO?D)uaPK9z;}+G=2x@cKp}go~^5>qHvQNg~vV z-sN5fG(QuTzw#BFD_vWqruKwFEYHsMMat-p#X#7)F%NFMxwNJaekNEna@%F)ud|Yc z^W+OVm^q}_^pG@qQ{N4n=DajNU22E3)8h6s8oGZ(y3$DCQ?#mcVZ(G-a#V%N;%e^S zNYw#IgslVV8{6ickDB<+TtGwujUtv1cFzUM|4WD1!$YSPN1`(R75S7wJf7~v*fmAj zLIM3?tY|2^sUhhp5hZOg$@-U?ZEdMa7pRL|_>IurL4GX`z1sdfOJPOt7qD3zfUdt% zmh3>YhfZkfOh41-9%@0F*4QUCU!J=dktFytZ=NqK&RXOXgjkgz$xGSpHURiexm$WI5L2$;~gu8AvLs z#V&%--0Q@;T)`WHvO-sEo-4E#F&#A@f-Vt2LZJ7h_jNW9=k zVX?p9sL#R=i6k@~62NnkL1Q;jI6F~lsQY7SSX?aI6Qs(CUO47S2%cGgK4vU*CEOH` zkS~`3K{7gs3Q0J8gpJSvg?3m>%Yuavx}J`N4adVT^rK#p1<*NL63Z4|7RTQ2&Y2$% zE1rYpSpdjZf%)k16r|)TEeR&ytIcgE9cbc~e{MMp*^C-TPaX}@K;9ySwkI(%HRcw^ zGx~3RK~Lbn#R72fkoR`GMX!@D; zlS6(>BSP{Ij!Ob0+VxyUp>|gAt&$jN2OR&YGP$hOt2{!TVSYce85b*9Mx%lW+%0K> z)~-I+Ag<{eDpQb3O00>DAC+vRqYH~gG!@^BEt#~Kh76kli0kd4?1h%jSpT(b0JQlR z^4%~@gefo>pjoO3d&AO5KRs=I*@|)vP$jBrTW69bwWKjqyXOnSeu5`a#fL~WBi<|j{Z@MBN!ZfVVWC|nIK6ADc`{d9QD3;2@(ua2t@JU#SxbNVcYYd$q4 zaW-m+{f%~et%NcJ=SS~5(ta91kY$%ghFG=0JcS~^-EwK2wZq!V#Pr!T^lEBAw}c?>GT{9!)QhaVWW3YHn#C)UM(_G3TW3+KLuV8rhqZ| z6^J|s!)JVt8@H#V!i>qOvMrjLhS`|>u>~Z6HWa4)TqpEDmlf7bgxp309j73}Y;6&< zWd|xYn~B(j^U9Gw_3A9}ldHZ2E0yGZaD2gyZN2ExbuK%d6m5s{0{;)ZxcB+*e{m7L zkC_ZzZ!V=4B@$l_>LxMyX@Vw=)OM#%5}4Q~3TVrUFq^$Sj=qgm-R z3S(jC$4s~8sawnakyqYS>%Xw4%l_9)`9lRsUfHZFz4S|uMm zhZ0_NN5pg?cl7w@m&+qdzUDJUjo$;mM!l{`f?Snc%wVXXU4j*T$K}j_LuBx!q6F^8 z;v?IS)#kNARE)33OLZHwjH%m4LdOgY+r8~b;c+GFXv`xAshqK;Du=}s6Eku0x@y~D zDw^%V{OroJ8nT(;8>Ak}ezba|SYz3nNB3U~tfsP&Hn4m2YnYF4|Cf#3h5wWAn#ki+ z)(U5T%aPye{#4)DMN0RGj8-^fsNC>||*Q2Qch{=_+al+yz?rgj59C{#nipF&W~o`9pI7e8n^Z8d~#I zeEdPc){wzo?-mIYNt8IJ&m(uZ*CmZb2&4K~I@$%L!(mMrh#L5S0ToePtv<4N5K-KL zS^fYDfc*4ODm2x5WJ3G9qMBNobvo_Px6n22akT4eZ+`n-Wzp8Yw>RPTH&^A}RILBu zw0$S!J4jtNgdsJRiKYQwe7c_g3SoxI&YaO0QTYc>gl%lDJu;ywZ1g=6sofej^mf{H ziXju+-?>r*RdltH%;d;=<6-lF1}7G&H@DM6f!IiFJ)}8M6l%sK)t63WkJ_b=mw($C zYZ&2`k%4zT>A;L1S;Hdf`^9+moDUAjs>o|byJE5lL36EzV zb$7BrrvIhaHQyq;F0=NowtAYy!@UDa!OcbSH6YcmlkMI(3=b6AnWr6{l+wNN`R=N` zbQP-I(Vqp+KPQDWEqucJ{Ygfsi-4?3_^@?8JTBWX^6tUR+W}gtCcVqcibQd5=4}d> zzmCa|qnTfwoPuxcLC)TQpF}M=n2Qj}o4N^7Ky@4|_q{^f9fpLC_{&Jj@`zEIGgLE7 z>0@J513#gENWumhf{8f60^C8Srn9$D>DpF9=`h?<=4sp@yWcO?%tL<*iOx#cjGY{i z)y>F5Gs%ATBJK*BmNJEzdNiSY=Zv}f0@#5io(;q{_B^U%EDjmOqb5K{++=j3`|;{(@~)ot zABtDk~LZ4eAgTw~&1-p_LEfCQPeqn91wE%+I59m!Sgx zR&&X04IRldNgu;@%+FT!s{pa5JQlC@pEBnCEJyL6q1halv`ya+1TCGli@9cN_W+?gGwU7;@+U9FTR zw=^x^Z3!|i=`qH(`V?aliOqLhBK4MlJOT(Mb_)qh<*ou>3&o~+t0ogf>aq*}t}gWf zm}1(pCe>Ar7a|nm?+a{?bi|^9*tw$JY4f2&sl;SKZcaGjMl{EI>Bb;PZaV@aql57d zDw?6d(NNeuB|W@GRHBMCb@@^uQb5WS&bDA=)UW2;%3|+z)tpF4UNt-?wU-Uascun> zvse9~!%|@_*XJQ4x356;Zs31ms2%%oj*poB$kB7r8d6GcM9;co3kA}a8N%Ab9K_@d zgb_xYdb^Wm%aZ!!5gD=3P<@UHqF-&Uh7rujbVzp%-@p%&Oib_WbVPT>fwKTner?R% zAPhF2?la|@woM4P*EWoy7QW0$7 zl8rqxk@$ZS@y|xfxOQSr6iLtH6XEqr1$KU7;WUpa7rWTBW z`vsE{lqw@9Dj?oJ>Lg5>h%u?Tc>OBBO7~@aC~>N26}O@<`U`(B{+>yyr8?upU*EWp z?B6WXMt|_>0FU*GBqpQIJ%R#=7yY!P0~WQ1C|~GqwMRna_B))?h@$YN!O?W?BW5;Q z08TOR(#epq6H0ebRH=o3T+d;^$@zm^@>;r10D;o<=Q^@;ZH0oVEw^Z0SgPllgA6Fau* z&mi~sJggCZ=)1s2oYpPLiC(20q|Tv2pkyj0H2BMayw&FZLMp)Kg3Zkw&6H0Wg|nbQ zNn2FcEtW`2@;gz_n6rp2AfUy6WXoi)CASTgEk^{afHX)DJ@J!$z~&7l0Vd1n=cEOg zPh7!2t}PKtirIz1p@X}4)Z%JsrAD}UjDKSZqnQmX@6hUxU00C5=oy$8mWuufjt5mR zQ8lTCW2KCA7v%Mq3gMi{mhCv8DC<8x@`tv;L2$uxCL>ccq%Mh!E{O-1a(6pV#QDA$ zEXCRd%joYiH9c5fCiI9?dOTtWSACdaUq?jhsjQ-==UE=y;^F}enS7k)2Z|F?jScia zF+NK0d0pbQtJ_tsv=a>A(}mZ!fVAxj@M2!#K1Et9Q$FGF&jl``@cq|VvQlTeZ=;x5 z9T84KE5T9ma|J7+b7gz`>RL;?V_|ihXM1(4M`dTe=?mF~`w%T~ z9R&0^&Cwdm8@4rXePi_alYnD|Ag7o4+reBa25>;BPRNsbioG zjjwld@FXsbVANZ89FFVurU;DIJQVOzVqfFlsD+RF*Dx#rBOVvh=}Ff1r)|sam#T_t zaJo?bECkc6dlkmWt$F*94ZA_lzmY8SUV^^g)+-6XB0q67d43}a(bDXi&F18vWGL4} zx#N%ex%^$2dVtI0i$)A?O7AdDcy2){_CioX>1fPkX|S{F-6sTS72m&GwD28K40RJa zgvfQ=a^UAorAQ~hYAc=6d`pl65#_%6a$5wb3faAm;yg@C-{xVP_qoFXNs{i$ja?P) z#s!WQlO>(EQgSYR&tYFsovlq1(M<~P*3YQb_Zh$XX!1m)g!X?F=Nckw^x_Mj3$G-? zl@;QtOo2J?t=`t)qoXe=%jV4RQ;UxEm4p_{v=Q+l^n+2RLP~yUEJl61CW8xs`<|-z z4>zQ2M;K4okJ~YqLKKO#Osrw1GJH5`KU1r=_7oL6ShOln*MHhNpHRGAQ5exnUSMQw z??#1w2k+YcOIeh!U+R{d?TW`zywfLAL>E?^PfB=>$?xh=4#QMdjOv?TjA$Rb^N?Qc zWTwDi`D|Qf{eu>WO*5Km$mSm-gH2%*v`elgAi$>8`-fK+F9WD`z7($ZuBLloXO2Ys z=fMzS=BUiR?c&lEi(TgH5cZ(a^xs<7=KGnG;`ZAR&>%$8Shh7c@~IkGXY$&YXOQpR zI)_c&+z~|2eg9bgL36=6gMDB7s}G}Spu?>^%vAOb?!uVZc(CVc!!q>Ro2pg$&u4wR zh}?r-Dbr#X|KYjNIHWc95nMF^Qo6$N!$G}f-QkXHLd0gfAu;91*w0vB(@%_Nns9>Z zD74#Nm;A;eT!32_X z3qKWox|&2-cz$)fUXHQ(k)zkRIpqAiEm0hbq2N`7K=>9bb-NsGoNS!^?CqW1?Cs&H zcs|v~YHkZ4rtNrW8?I~k81xmDmxteYit}~aZ*+DhCnq01-JQ@Fy&h|CT!#4@DFZzo zNd~sN4>6U{y~EnwCc-SZoP4zP2&08wso~b&*=_toaM&>p61yA9l9ug2b+Y#o$!{vt z3bD667NE@qB?4>lU-yNdTzSQjrA+Ipq3W;h`3jO!CUrRb0fXyb*V|Bn_VB}X&#tc$ z!kLtmW&IoS@wD6szusW*2?P5Zw1vWVyvqzik|eJ_8=C(JK-?cS_bl9HNfIhrkQ1G< zp#J7PT2>M2UQ^XL5*o(QCPQ;6L(9s-+iOWcaE$gH!S%%9@G2$IlDk5yTTmp=#+1=$ zCi2r1t>^P6-0M9t+cHNg!_++3Y%%U=p~uYnkse)D|0I^cT3xeE^rlcmudCiXxpwzi znb0a^0rRLJc-MckBzH@X$!pd+3yI`%M#;*(=Fd+3+k84+&m|#_S>Po9E6-P6xgLgE zSr8CCf#TmGgUD^v+tbQLw}Zi^ErPPh&G^H1T`F1xLde>`hNH4FQJB6H94wK)#*YE; zNTZXPqDF=qIxPV&y=y#NLhTT|0dKW->zs@t7+u8Ykq5Qf%EHDzOE*%I(+k^=A3u^U zcX&O3JR(=!Hhg?R`nc$#PsX-F#9f-$W)IGp?d)~q2UmGJFZh{DZW>`;+<+{{`jip4 z-)c64+4Kxw(G;f%7pV_RB~HTT!a4a$79}=602L8g|1`>laoJNBf2uw~j&6*}6Ez0| z6i0zsb*8HM^m5da;QL$2nX4;-zwHSvUacRb!EJD=D6i+p%$bNwp=AjQs+oxrn)Qj~ z2`p8ZB{RzMZ=A11E=AJojlD{xLQ`>U3)j$p5~`R;Y$uyUVY$OeNY0K_=BAkU031CP z!{BX;N6^p|)kd6y{cTVvHrjPsAmJ93x#C5mS$u@4g&Fn)Mg|~Sv&Z^UJXUaeVDFrX&%Mr4Jipy`7(>qK<3NqC>(AWM(wjlDUji4uF3t$oA37ft15M;W_d8SEVF1TpO5tlU zlGjqnYBhf%oI{iVaKEehR@521PT#w~xSCd+31g&dO+hl!B(0aabTYmwkz zOPSEoH|?9^qj^f-p&buP*2d;VD)4K3%NV&uHqS{IT+KHn?TIBh%LW#YWb7n@cSQ)W z>xWo$;lfXEMP^yy8hTDVz}Bt{!1McVUhb;hGIT)iH=e&?#JUl(?FhD#w&M&JavruH z%9%^9)_?ial)Un}3*LBEcrjnMFWw~9 zn`;vOG#s>rXHWe%z?C5Gye(qm_C5Kv(XmH@B|OiH+#B7(`1|(mVJ(~+!Sw2mz_{ChVQ=tBXd6Z7gZ~8i+gZr>!!jvKrkK)3IVofa#0?8TfZ8|6y zl%)XH=_1kr=MJiaK^=J>LDnxxI=HX*v!J#G}mW5y6o_64cWHNf&m^yFl-T)fMI zh;eJLHJ2fB2)GNb&o#{F`TmF$a|okgXD8=%?ZWrLvH8zyoGfiUHz}sJSn^rnXuc0m zwe#V~Mo`vj$gC`1J3Aigncc;y`=1155s$Iv&YP@{ewWz~ME{;@M0frTu=)0kC)NO- z{9dLM;Rx5o2qxLEscY%$Y&?6T2+2K&1GC^SgLe*5Mvz0rB(eby)ok7M92MIU+(^XW z1tgNe;6bWG*V58zf5qEg(W60QndbP#*e41pusGiQe9!4g$QWzxU=f4m5HPsikIyLVW1n^~zh^L+dFx;PL+U;IAQe<9yFv-k6Il#!81TCnTdBfIci{1dv} z5TE%oP#g^rJa`z0_`1r^$JcVBxAC|i()rwB|G>q?-ISD=EaGwh^0;H)by7W(CFrKK z>i71_4${XTM1G8iPM_uDz3oVbJj?Qd$D>jlUxErGiBL=g=*|37$?l-Y9bu)0yu5-Y zMbY|9$idXe>D%E9xNBr`eboJD1D8*IrTWW1w(B|cg}m{$#9(N45*%RU9cH{EFujOL zM`^4IpY-;?osCa&OjA-F+Z>6`WeAEzJ{-Hd0$=Ymt5XIkIf?w;Hg>6tdx7^^SjH=J zNHL4i+wDZ70Ca>c=OJqqBD`d6u=dxX>u?NYM1|0D54C0CGB*LxM`&G9bSjrE+GoH7 zmac|*cZrBv|&h#>68$8bF1gR-}f&2Y|vhl*tCTqiHwULQ5&_zstFHN(P5>d~|-^ z*<<=MGDpbuxHT{Yi(V}=VFO}bnsu&UM5_Yab{=Vb8?ED^Q zio^Y$I`RiFkY@KAtI*CxQ|oN_AMHJHhSG~J9su{L&0FraI|T#%$MnQD$FTUTT28(rjVHsldo%k7d;vHT+f7jPw@O$c&k)pk zo(KRZ(0YZ5F3wE5NtPHhpR7!yPuqU)%Syj17rs*teboldB2Onq7gWWK%~8-`l3^zJ zp}lLxu~>}v$`aC>x6N{P=K6!OeeMDa{ojV)%h23{tLwo<>q+&TB>qY3Md!05s4(Ek zdnEJ>3j7u0O?qHp{7%hRl#Kd=3Jx~!5b>AQjU&hvD{3nq+tb| zS0->cuiWj?3;9|gTQ-nsN*eyPQ;FZ^h}o94QtlRwlzwgXI`E}-3j z&6o*AF@ib2QcZOw{kfQ`YL4%eEocP_;MC1yE2k^`MhM;GrKZ-I=G+?$FcOI(%=ROP zfAs+}pvL^!>Fe=D`KExg%F@6jw>+$i31#@W?GyZuaMa?gwFu{@{(d}P&T{9Cjew0_ z+0Z{ua#E5E>97f@bs84$8Bp=ylZrN-nQjq{TwO%J!i;Mk8I5oUXC6H=EShIWc!Tdw zy1@K`@|J;{qx-F!ddn)|5Qys70=ho~!l#ZK;5l7|@cx*%vjR|cNuYY5;|~7oVxXnbc}|jtgD2vNgNDi! z4l@(W*nBq1?gH=D6SE=%vefh&HOo#Zo~8?*pJdh0*vVSfah0vCB52a2Pf~_=@CnJ7 z1(aJk`(w16as6fzPUvc!OQ}(Mct~EFyVqLSH$W%&L*;4vg(; z?Sr@L)mEbor?ImGyAIc>#FWV3g!n?g_fMKSwFK!$Xac zq;$qfGbPE?^`H1meRo-gr;>^Lw=t<>mHKvFsCTg_38HgN7f`{IW-acIIMQq$jtvp; z7{Nvwm3?}4CDBj2udR6Eev)8*!hwN;0|16hoyWs(jiHx^h`8>tgs!Lhn$4^nvTmIJ zJOshK$oJ=KEZ!F(qN^{f{}?vT9Dmu7 zZwunK4bH1Xfi;7T&h82&^nDaPJU#4AV$t5bbH@`c&`{Z9!HJ6hhJz9i3gAo)W%yOV ziC|Ohr%k5>Au+zh${PT{<@DQF=1Du?$R%re0$|#4eMUtUUTo&RnF(Ad1h?2g zr*No>S1=52fAA`TD+^DRY7ewB^%G#B*u9_8%1MR=0Q{wLjd`%{#-59dGA z;d`#hpYEGCoOg%gu%=0)`gdhr?^nq_1FMmcq5g@U?b$D4l+(u!eB@LI>kbH!h%elY z6gmSDJyS&jt8Pu-H&1)iFP{Q|7*l+!i+@~O0vU~p@GYj7!|KHe3_|SDtJdZ=^)d5} zi9o^}^0G@FTs1}?gsCJrxMk#PR*PgD@OppVy%)AtBCsmPlXS7e<}&=!L$Ao~!<|WJ zYA<7+{0BNy7eXU00?lEI+EhSD!zw}jS$GNWZb4qosXs5 zzLQ!a*J#TsB!!7{@zViU_QGfbKx%iLM@*wSJI~kM)8lVwSaWSTj^bEy9ve^f(JwjLY11Wu}lX!uf8Fy%ZR{Kl?L*fidxMs^fCih+@glnCx+(gY;br1P+7$ z1=CJlcOtn;Bq-PH(>+pMI}N;e$VpEn*^&A@VGBt<=8G83IT~AJlV7ZV6xz(pKs%4fGk-4D=~!t9`IC z>J8f&TBxzodd#0v1-JCZh30>s2pD{=KjdGE65t{vx-5C{L&tdVg>zJ(5|ZTi@_zGu zxnF+0M1ROXlqOt{Cx+9V$YCD)rZ`uy;#z#4q($|5w~$Vr5RJP~!%C}Kldy#uZ6dJ$ zL$_uqD8*3PP>#J_U0uGZ6d0(PDrWHE4xj)5+A&-psgCV_HH{VujPX_(tRYY9AK}TD zj-UDPDe{IbCt$&H;JS&WdkPAwi@lf>bfvNn6Jqsy>JP(};jvw5JQVf)AH2;nz1hzw zmzI9I_|oD1C@hj=56^Fb2;b+5D&L8?_N4g(*qQ{Yel*rgY`=B8+uHqScIg2Rj8V&B zGqw#wd8qsd43(qiyYnxmVr z;*?}#u3CtKP+~)~`q4%%!$U1pVrY|#^+(du(FX`RCettSFQu>lWMP_Am-TEXrIf??&4f4*e4V-KomfIq1APEv@#cg*+)C({SbPmKrt0meLU z82!HamacWmML_hQQ@S1Vs;S1O>Iu#0WgFhN>n*EJC-U6Rd^cjNZBV7XQlEmPMK``5 zD+T#N6rwjzIBPL zh~ebtiu^Z8o_M%j!&g`i3Du-w|AxPe4)y<-SwhP~P*TVujjW@8rJJGNb4Yy7aa5Z> z?e9v5SV+Eji^+K5u(@qlp@w5t{|7cA8a?VXXGG365609N3#22ksK_+)6b^R|A z0x_-p6LFPo2z`ZZw9!K=!F8Xr1I&a%=Oj@$FC|e(at4EF4q~-aV_vp@csSECjFCLH zxSKr`7^PQxJ#X9^1O79?_MM<#{Od;2di~?)y@xwDH%Ecsx@l?LGReOFeVSbOZ51<2 zU=9AG^TDg6L7U4dsq|CuCeM0C?>5u#8&G|o0Og>|uo##QClc`kvm3o%J1EhmnXm*iaQgm>> z9_%r^w)K5w{k91QBr^|#B;nLujX3LZs_3q+edZ0hzIV(T8qm6DdVm?!JqjWZa>i-t z0c3h!A=r73eM@ zdFQQBsJKDaIN!?0#7+~D-Gz~n0(Ck~$jJTnVLUxc%T%+saG}$9@l7t866A&$e;r_c z>1k~rCD>j*d2|e z9o~8V4OA7{AnQ3+6F!wTS4pyd`~1P#2Tbx=>4|BVp$dZ|^cxrF zXXPMNOh>JJ+5w*jJfGmxRk~b{syR>rnqOC*udW6E_WIPwoF{g?SSc~*gyPmE)gN>3 z2?8dgq$N!Il)>K%k^Ee9GTV;Sb7%isSz`ekVL56FvqWY&P4OBf391yJa)^xDnRHEXl8(`U;@xaUZ{rvK`UES72dSyOnS ze=zVRr-XJvS}r9`nNgY6Xdci7OJzhOpqw-0V8!cBY}soH7iGUO_nj!d42XZHTDfdI z^k?MYtXcUvae`a`ciQs>=N6Gh%T^b@;EM=E7L5?gN0IO87uI*biykyr3Xe1O5cc<4 z?U1!|?sZ}C?-I-J?@UimPfUPRgOxj(3CN{V1KDFkQg-BEUpd~j;XxiNTGS0WE;TeR zw34+bV|09J=@7xb-Xy)$s&(F{?d;T)CBMfo)3yRcFQ7=Y}ae?2bD&R{EmmSOt3 zeQ29B%A_(9fMo}FJ{5>)EZ+byf*jhKardcvM_Aum7t^6b9a1(jwD>6sDih?L?YbNJ z#21T-l&P~w+Smx>ht3gw6_DKg6#2DCM=^gT(L2{^iFQ1xa-_0n0WVK{i^?jRU4vX%NKb+&Pbt6ob%GdK?C4YMEr+J>DkPxg_P>b1FyG z#zC`uVNy)~z^&Mi*vNeOGo^923Mb35Uea1MR4X}u+axH+zff7`HXGBQMf?bxam*BU zdAIq%m_fZgb|k+r(}mAE5mrie5EBy(6|ukq-z8M!k*~tu=-d^bRkWHAc@Hsa^$)w{ zOrvdB#{=2PHJv`*W8NEE$&q?)EtDHJP_oilPRbA(fgwMtS}J-%O(SBtOTQ4;sZw!% zxaQL0yKxvd3E?#fDGErXlGwt|K1z02bRvSAve3%h_pYi>EYT;3PolA|P$>(^ly5~9 zA3b)j`ToW+uG?XAPV9bNVu-e(!M~zxq!#aqCJj$*DJ<}6W?h=#*vcRVNfxjvMMO2A zFTx6p8&dp57CLB7%17MmkQfW{6I(`)*WLunX)d3}>gTZz{)0qEI=NqW{UhOuUHXRn zpR`x4ZnIox=5?|ckwZ*IvKF|=|43apEYlezbFJ@zySHayFxlSzGk4LeuAszf>Evdh z($cxTrIb}o#W;pgQ&Vc}rh?kT198R}G)$i$cRzV983F9gWGCJ$E-C1}y-l?9^qd9> z2vp^yr_T=1jbMjMB82qi=^1WlnAE4Hgn)a}<7VOp>t<#+z)QF0)KbvYx+t^=^lRT6 z8s#_TBw*aSxS?IT9xqKCvH;spGbeL6UsKOaYBb{_gAlSPOuQ-S)`LCZQ>cJB=#R=y zEn}ylFyS9;lwj2^Z+sqLOViiE|!XT1hE0kJI-Lk%?EPzzL{>7NMXcRe=A@@Toxl4_9UAG-s8JL;zKt?(a_L zb%RpZPYg{=5_0+JR6Ysr(*(QgM=?mtK3Z`)LyhEsClq006k6{9e5cJhmgii!)}<@#+t z`{||}e#d;P`HL8?`2{Ir5)w0>jE~okQ+|ep_5YTZfQLIx?~ZO9inndTJ6qcT2H|Wp z0o_QFlEI<7lf~*L%|+e?#E!X%12)4|kPwI3z>VZKO!=^WnNu;+82M$o@h+hev;VFK z1OLmW&8(S)<0(z?5R26ccI5c3J8RuxZADK&I5?p`BR0R^uA4kxpY-%@>sk_hEW#iZ z2j{onBP#V4h**ou>;MDqc4%r-LmTV(=0Ep&j{Tdw*hDq~xQ$isT)f{9(LS>8F(T#i zC2t4VA>_~7It)IaecumJUn=KZ%Il$Oo8S<)6HofADA|#Q9$Z@!GtU%@4=(?rwdJO)m0EkojMmhhWyUhTpt=1vvZxM^)5iyI?atj*GgBPA49$R zANtqrp0gglAc(bk{f;K{DD~iO~h#ah+a04`H7D#TC$C&(qN;_ z>tSNZ?R?dDe^T%wveC#+;p^p+SJH2$5fS;w|l-N zHu5&5*0u8fD9Oe$hI)Ux3*8=97*bhKL9y!m_Os0<&isl3e6Aic8=V zqh8mj=ks4N)!r$V6r%s07IQ%N=v^8&^E=8v(XsBd`A#SGIt<+shE66JjJD?yY+xm{ z(3=c(Muz$*lBqTX-J%C41n#ySA(4FH1O`q!Rad6|bDlF%m} z$&Jid_mwrRH9ivBc5)4N_#7pN06~!xA3RM%-Fa#Gz^hepR-ajs(fZcE$X`Ob%`rbi z%#!hx^x3G$cJTYxI~?zx@N1W)j*;-b18?ifVk$`F(OK+@U2&CDIHO6%&p+%!qJd?Ze$#G^uG7muun8&dz{-v>#+QK@VS7jWyiE18^rxb`}7$~tE$#`xY-^3 zK&0!DCyCywMxPp%g;Z1xeVt4_pX!n=#@aSs&qeKjz5V+Yc%YQkdqRXIu5AP!w*keqkOB>OX8$L4huYsAI*iS5eubDRcqTT(2 z0iggkjs;}exT2q{v10}$L^G#OwC#_BOch33C(H^%iHepEa>R0IT!8reyb1*qydg`X zw2TR4c~=@`1`<2ZIH@S_exrYxLi;X&pYph6stpkl_3UeoO~3Vy6y6}_|4>9KuqKHy zQD}uR3qP{4G-Mhgf)wb(>5hb1JMxzs5u@gge;H?)b4>Q)b~d!Q={|MLQwR~(vjJsr zrIMDc+hKk$@vr)03nZf{9%cvdh!2WciLOjFo80X;p_PT3UrB^24UH#I9ka~@X`}p4 z9fsH7=Bm8*6vD#3Zc<1t1nY;?>aa2-bMuOd6D*b-GqXHXcn2q>&lDJuSv`x@`A5(@4Ne>HW0PSfyb4O0?P-d_O7l)4=_1@3bk4CHc;H+hqPIovZz z(9LQm{hz>89T$*SE6z0w%5Ow@a<}Gp#mlnzDHbB1&-PK(hU+JK52i71oRumWVjmjY zdY~WwnEqW$@Qnl{{lJB`i8 zwr$%s+t{{^#&**<`A(nj{Rw;Rg_*gpxd(n^?A(Z1gX1YHOq}MbTOeEm?7wAW`o3Jf z_B%K8#XN4LDWbD8cM&7u_?hv!lG|gUR=3CJS1_eP z=!Mhq1VuNe=d;Gnr|N*C=XHy3M&NO?rjTqY;`Rxy5J{Qq=y5(m-}gqym({&mI5v!s z41Pbd?VdGcW-Kk%C^8+TiwRcm?o><7r2hztQpwe^M@=0(E+z#NeZ%=iOtcxD;p=sb z#LYA&kU(HiC=nCWEdVIEUzbM!mtQvKU)s55suF`>N`f76V2$~0S4H%>R$M`0M;J}H z&w_RD!UFHo)-u3<>Y0_?H7~^Cz{XS7Cg=}W)z5v@c1dCto!Vj=m9Apn!-KxsqxSjX zq=gx@bl3oG1=)-sa3wr`?7n35Fj?87bH4=pEu4-WUZ@d`b~m35U${V9{E z$?YbOPVTH{G18mDA8bql1(Q2DY5kaT$~nQd3fs2rTZA}a1##yKE_A2&_|vtZszrBfn^Ax? zqbfkC)xl=xv$HaqO!i+^BL1`o?9u%5FL4_Y2@2xaeYt&h5C{0&KQb-B9 zBaT~-+MI~}Q20!4;S!H`!x8vq40S^wmqfcf*@#Io(HvLfbSH4;w%2l;b6*0U!2yNR zpel`Q7%y5{0HZ~o3Vde!I&bXT8?UUK+zfCocwrIU!%?%pULkZLnst{l>&}&pnC57s zICo;6V(wON*(x&v;xNCyBuRqn@k3>TO|~JTxS=qWs#%-v1ow`5Y&XUm9UsU&TknW% zgS27e<3XzAbqy@*Tr~f~sYjgtFP=fHce~cx7!Y_F6}eGo@K#1WyS?UJrr@-Y$qR9!V-*BPdZG zG=L+>}XCzom5)VLueG`+6 zA*;{-O*}lQ8 z(y=`@D=0e%D&UJ0}}|J@ydwt)NuInzZz+7IZBLplx{BjcU z+^b>1KMd7pnlVCz-4{p}vTACbKi9VTr*ZZ9v_^WX~p?QQJ_`KTW#JQ8=c<5`ei ztWzRiQcPETMjZ02u5=+2#q2?1;$fo%4th4>GGxe(Qv`C&vI?;pt=M^qZY~HvQaegr z#-EpzpnRbx5KWqhU79$z|LG!RI(Pa91qPOf1x2`L#Q&@_LpM(c^N`kf6*lJC9>-~c zL{*30=eXG3)G`cj!&L2ZG2~74f!3jO7z4BVGIp;-gxG!bSn~$T{^byDwb>fi!_G`q z=T3{^h$H}CWybdh+2^vr^?+L7zcv$@aBbT*Q|-~?S4CFT=@B*vEtmmN#5Klt&i4TkX1VJ%{?dZ$~$^wv&vNJ z<$Uly*OG&KT3=i?F-12HQXI+Jx&^#e&+fOe(Be87>rygh4zOG+KAm`DcmV6cd^Ijn zn*Gb=R(O*O?Wp_2ow;|{S6|?sHvz$&7UmdoRPIlLXyh1jbp~{k+a$wBlc@+aWL*~> zbkG}X)<-8F6(d35QT%(d?cQ(y{&_heZH11wdE1~hJ1^}qXbP9(?IG`djF9i|f#16Z z1cFQ;!^hT6%+Hn4!`co_LqRj%1V7y5^>WwDn0XbO*?vwpuSgA`+J@~i@{fT ziJ5+m%Ka%1QKFFKMNK2k(?m5`B}SYPyAG2jS1TV!E-LBeCv#W?| z_7uGC%9@EfsDr9sSrKlt%+ znJY2-P^V@tL$9U6hsqK_c<}zK9ziq_deY*?u{1hr6d7P@h#Q?JTI%>za}nFmo+jL> z$Y{8m<;ACjpe%Phq`D$`=Gbep*aNNW_m053Y8;w%fyvrkJn1=CnHu2L;Pb!Tqnm$ z3z<(+?JvRjB0};rq03FKv;0lh7gTRs5c9!uV4_w5c?e0Nv!bZtG{~ur4nyTk_SrU{ zUo9R4)`cdNjTce!OXFO|T9&@eqkuDd$pv!uJW01nPMma;7*+zBEIiQ@We(CJxoT1_ z3D05OG+Vs`Z(WZMJIgd>&B)gh(5p2hU$dS4QnGDp$lK0PSlJhjQH3BH15sM8Tu+X+JH#TD`2kI74Eh7M#ptsMTHlYfWT+xlv#(ZRQe<|9PtostJXsl z_qIZ;tUxXecJh-AFO*JzO7)25UPrkQc1O5dCbO6`L z4r506*aZ_qXhT&AimOv2EkLce7q*oZU9d;{oiu@MuWQ^}RW1(4Wg(WOLf`7$Ou001 z{UG1h@*!a#OGlhJ^TQWsk~dRbdsbCJwZ1-@NQoAj+mnf%70DwNWuXV08dG~%;+aAR za+Mwg`G^e;$Kb-}`Tku~c=74x*#8a!pI6e3$Nl<`ngyKgKR=peAKJTbiwJ$ng5on6 zK$WAOdXNlt+RlpXcI`DA4C}zbm5s~;0C7(B9fY9DY7%Q)ZtOs#5sUO)?Kp|kyFdMC z1LO9ha^QQ7h-5TBV^Wop;CVQq4*~v}rB$Iuh3}MMNH-yd7`?2Ah}3b6I5>UWh=Z%B zxLh~p?l|hb%n!ku=ZZf$?%x+~^{n4)jL9n1q>h_7w|l-m&=!!jA!DT2T)9Z4fYGXF z&8=LIpc5NX&6BjWW0Z7MLd(1Jey|D{b;pR zYc!4GnZhQdrS)97Y(AG3wtYhr>Q8TKjhqotVbb%`@n6@y zP|(Pq!cA)z>GFRLI{I9Dt7^HcNU0R9O28NfV-^sHfr!czzOBaOXQz;x)eAQ!I?lT**1 z423*}7nb*9no*7KZP{JA>u;FDS(N(s(u85Dh?wZ@oT6hHFk1kRHe4Y;W~C#OF;4g2 z9crWhnOD)Ff`9=H=iSXV0l1K$iTXjJ1MBM6)~D>E)~8PwXJ?(S-~-kW9*yQrWE0o2 zyd3PTAmJPC7b=hjkh9;M%$7+%rUbqbDiGZ9 zp-}JVO+Nj%szP%Xs?6aIqeZ0MD)swh$>7^~$&41~y-RroN55?J6{v86qU80;?U{Hc z+4u*{x7rxP5#nE17WGBA+u3|N_fy-Cs6MMxXZ&V|#AUCxy4bA&1vvsSgYr zt66ZNR#I=qwNV{oI;Y4o?7M=VARWPovkk?Wk4y=MCowK=Tc~12rWLBCR{u0F2SVt9 zz;1@BkS88NWWiPr9svpP!TJL|Pw$uN*+}e^b>ax=K~!Qlt+A30LB#YEfhFkd89TAi zAlWsGcVy;uPxe{Is*9cKmV=W}H6clAU+y67KiD^0~UTwAFSX|7c=(b9{Kn zcU7f#DF0tnKL?x z67e=lWxLr7$AHJ(G7A|4D=xX_PZ|C5mTEZ#W)@b*>@G!WNlJ03+7p`tKzmTI&po&g z52jy1BTjlxc!IDSi!q!5u?2fCdqG)YodeeX28AW9(Wlvk-w^16g`e4fXx;t)%9CT@aiYr!O9Pu7r0Ldxng?{!X-Ra`HWyCb} zv1927!@G^MTZxW;Z=;dYHM;TVBDL+CTfij<-vQHkJYmKoafaSD2+$ijn(CD@SrS$| zPIZO*$2V_ldAqy%gd?M)C*EA-#eD`?l%6IwqW&*$6mZ0tVs3Y#|MA_J+ki8ch-F9d74(A;I) zMRtx}lgu4^qY(5iQ;SayOaH@YZ1MlC8z`_9;3+GmxF+iHPgR8?I@36h@%sC=wE)V2 zGtRk>2|%rGFWU<(%m)Ipyb?Y=q3y3iLCs+>9G3QHifR@VCcE6^1~g}BR$Be2bdpT0 zFvgnOnqg5tF7J<1Ahv>&bMVoa2vBwzD-zO^yO+kzdU?>%Gh7S&kjo3@I;5i);UwK43?K%*OVr8<7 ztac)i)!cE&L#ahYx{F`_=s|?bJ=nN?8CY;tML(Ob=!f^FL-L^eL+6se>kW6d zmgerG?Pyn^Z0d!&s$7~C-Ugff;+`GFi$bE+CmPc1UEp*;_Is;*!gFo6l_iT46~ z4Ibl#Er6BMf!lkNguJ&|(Oj+nY7sX$yRkf1j2{<3fmTx^n+yKCvL7S!f@EeRf4^n@ zdjI8d7@23g-b@X0^IX9~Q}An2E!+Q8#~gZ|MZ1#X2=xjh9ujjeWTyG?)hd#%9;;5p zZ(jBcs64JbKE=eKe&T_C(80*nf-tq-lQMlI>iy?+el7wA# zqrOvlcpQ=TQC|eo{x;xGPp>l>$J#IKnBbP9fCNLT8#MON{GWLDih>6xv*_m1S)&%-Z=J-msF~q@Zh6F zX@FB6IYZFwmw(S{9l$dz6o*{NGmJ_~CiOfa9i{&uf`A6uG@Fq_-rA*;B zhi{p9*b-DIqN=$OA!?`0y_OyFY3LYtDN66sKPaQhr&tOb{S`jerH7ADwTNLOgz1Q0)vY^Khc$%+6cN0ba}m~~DkDtun)fXEDc|D5PDez}bf zPLgR;Gu2##R;deB1bKEdo>({>#1PCX%aRT|t-qHmfon-st_wmcMTyS$ePO0Q`p4jPi zTK&7X_1t-FP4C5N$}L$jOu4wIzwoEX(Uj7g3qbKO*nr zg$-1`t&dV~7S}4$;gMqzup!M=0hxrBK9!S7sN%1(7r#1t!&BLC<9|JXon%j-?B6rG zcjLbz>kCiv#qccSCLE9UUE~a1RCmcZ+R~4e$yCJ*BH;RuN`>Dy8if}70i7VCzxxu4 zsYmO*V5eODd$Bd?IzL4Sy(Sd=UIs|$0HZ+F#Z!CUqT@sTEkA+#S0hbcO=HFgQI&*se#NGS+Ku_CPKZ%oa=i4URp(_ay zjy4f1h(r+X3YeA=Yy+vQmv+y_@uDLj5pe zf!EwH=+9cluKzJ1-MaiC;QV@bd#Cbxd%-f3|Emo6E*cYrJ~%f4wb_k5_UJX8!4Cuh z^Slf9Iy(my`Kr(w0Z5op!Gc)nSh@b@>p`8ti)xKjTtTK)@S}!bXbk=l8ftre(2qFX zx3hU&ao$06YMXWCQ&v8=S)acitK7ERVxE1N=x{)7Od(7%eq9&vm@_p(i{7m4tYAGH zU-V@|MP>@((+Q_mnx2`^nq?I$Two@<`7bQ=Vv;Tgq=ptVwvOTVCk-HeEy4wh+DA;O zMhMay5mU;nDt+7ci;zw!C!#Kn;QbzPw#;2RQksc<&M2obn4ybO9Wt9%8)!Pj7tWQ% zB)m8t%YyIzQc;%Tn%Ml?OKjgot47_~#hE5fbuxhh=R5|rR+6=lcP3{Aa3`+T?6Fg} zb}V{V^5l}R(v0khzZgwTF)8$$3%$*`oV3{N+!5_++e}bwj;`Xs)BfpjXV2;LmXjnQ zq>d*@54sM>=_@vPH;#~J;V#slNuyd8rK5U(3#G)>gg(J3LV##P5(CH(KJVV)sOkuf3xgQ;( zaeC}&aQa>GD#dsv!pM@iW4uz5%k9w_W|GQB6h{nuR(+c1DktMQC?mbv@udZ4#7AXR=9&?guL2`A9bfy|nGQ5;yF`P$4!Sl$zMkuJ!4|9p> z_wFcmQx$`hYnN~Fyq`Ix&O<%dV8?>Jy$_e9;Gie`+8|0SCG2#4pU zza9(zPYBh698HT*R99+9@orc&fE65e0s?^o0vK_5U%&@Q25hNWU%}s{!0Jf~U??Og z02J^@E#4WjMcmbe%A^H%$|I~Y zwzxULbtrT0qd}@qGq@?P+R=}SznP2G&!3q&3jLT2{T$+P?_$FB(RWpJo0l{&w`lm^ zPQ!S58WHFYedF$oLLr4u{ZiZ6>034RFgiz>XL1G{C?v&-st%&_VNU2mKz*RagCQ1O zR;AUFrG=jw#BVeow@f0I7`Fm-I{n9WvL32a3{yb zSjJ{3DleCWE#`*Kgp0`hnEo4P-=`6{^L9q$`?xW}#LOFQz?g1AAqzpSmaI6p6&W#o zuUb>s!G)Hyi>9P+Gl+jK+v?N>cy>jir>#TDP2Ubni{xx}g`+kkHxX;eJP$+tbvZ@R z=~V_hLF;V49-djZ-^=JKeP$ zjUh`qrz!(WVO?0f+U(5_63_2E@jXsX!aJMd`;tHx1;c;0TT6csGJpB&+2`Zu4_JsG z+IooJkcNv!?0&}^pN~6XZWpUyP@zNOn|xYgHk2Xvl%w3s94#td_X`g`t4w+ZG@{DCI~2~N1WKk*OY2;yXWeCMGKfoV;6)Vr z+Q>)wFR_VtT1R2?q@AmYu%GNFtu`7##_Gfx*cb`@SU5+7lXBKF?X*inyxuYmo?thp zNN&o6I-W3V=&Ho0PeZf)W&V-vIOFnl+Sw5+6J%^SziyQQTCkN1KK<5DNxwX^ys-_r z$#^JDSnM3QcrUz^xrOBr7Y-X)c9GC`_7-;oIt&2#0PWyV6i_Cceg(0S>{|$Uv_;dJ ze2s3`i-&Nxuz`W5i6XQ&K?B(a37bp|QZ#KF;VE~r`EtRiOHKx%lPb$1jKXrQ`T1%a z(ROD6e?>HXE35d5Gf}AVyHFv@xTO!}Vc9gZt5KU)xZ#gnT=gjOACql=L?hxc`pIdK z?mzqq3F@Hr^6dCSfqC5gW-4f~ES0OJo@gI`e|S9Y5+3ep-^Wk zstOyWd!*N?%8*h(PAQZt7?gfMU*xu(Bx*w*PLG_|Nndj-l>$?QC>BCV#P za$Uo{=Rzaz;0d=nJ?_atw>lW_6ejfZ!KF0san9dF{bwdc+XB)mg@~kby!LZ1?6GpA zVl{cLWg;i2a82thRaaz+z(lOf-!CQn5$SfOQ{5~_RI=Q;YDNc~XZND4%gH2Y=w)ta zUKnu1CW$KrMwCy&Y>&|!J;Kdl~4;DJuz=eSllYlm^+s(n*a8&rn4~YeWqm73_gp45P zX4P3u_l3B_%_Ro5hsdkRh1Xdf?Nrs2MBtgWivw9;ZG`5$4)bvKJR=`P;XJ`W<(_+^ zB|LoTfFL6bvQnG3=q()TSMi{%d1jowf}f-Q$UDD#Ir!7V{5-VT_rHN@q0AbETLz+xfT9PI&)UQKdHz|+Y^k#{_MoX`S!H#b$|OFceJZu+hSxL1Xe zXKLG-QlnN&@v4;|LLZnoMmwgf%4A_V_JU}vETYEc;1sr>8tgoCb_{o9$-?u_6;y5~ zk4@rAKrVUS{I9(aj*)rKRoCW6R{|dW%U^~ZJ-=I(yqAejFwg{)0B(f)8{CuoO|JGT zTdU0)I)g=s47=q%qj_C{)39dD*?;sUg}T!WO=+p>jgr7}%Bhleh7D$Mg?ss(Q+zqU zigT3(O~rV5@1&4CZJCgk23lWDo2Z0py~%vp%1reoeU<;#6z1EM_T9~-KISeDq08Q7^YTPzf@c#*HC6^*6HAS?P#P zu$?V0{kzV3ODT#dJh{Q3j*MJ9(X~qNe#j0;QWr0$ENDMEGzR`9FRA?hQY2m|) zIySO5ps%Lo@d8fhe$4o9uPjjJIY}1U;*Q+jyOQT^lns7Sk!8M<)dcIZm?xJzcb zO8d@Jj%RMUlgv;wUm>H?S8n`tFQc?8!q??+Nzhk+Q~UOFG` z=T!zyxNa-nCNs*3iD=*6v<4AHoB=fn$@v2prodWuUa<&OkJ3Q*_RHPB5)5b8E!L>k}^G%VOX1?zF8nB;Y|^DpwY>Uu_WP{rm8 zh|~6_d`6`jAqnzsh(1RMB@7HOgazbW(SBjr60wQ7hnVDJ5`)pygtZie#NtuvMOX;} z?;bbGR2mwcmEQu&cx`q*VX3F3{XW6KFPww?B+bmE`WGe z6e|f0EWTS00N8xj4J$*YdlIBJlN0WJ86MzVBF-(;D)b8ybdX_z%{55 z`;>$T%jFLYVt7Y*e}6wYJrz#=Q$KlrZNEFfa&K;C0Qc%p4-5VNv0o69%^k=C8G&9cdsLb zQEMd>RwB#EIeU=#PZ&FxK!#0rT%k%O`C_q|p6+!B+4ZLD50(J9xWX%k*^~nNqWCW~ z)sof4-&X?x*vDQXH=(SP@iY)a#c2(-n^omX5%~}arDtn?3Er{HkaGp1QnA8R-LPTw zQcv?een7v!y?OgRJs&Q-pPNptj?a!b&&uq?gGRyLkbsED)>&-96$9RTog}YO*`H2~ z+VdwL>|tLza#R{^B}kc`e87xiWF zc0T9YBYnN~qWQl1a~7jy6Z4&jQCAm^3Z5w;vF&VJF}&5HU>!$DPc)@W4_mfeqMa+; z@}~k1E_^F-?UBwS?p73d_EDV7LG`Z!@T{^_XqubbAfki`d=-Ej*gDqIOIA9O%+dM^NP5(b`RAv=4+>5I+_~QKz4xKgMn)VnIq*+GFz(*L;Zl*{ z-5Ds1XW*_|!ZET_d@7EHQ{Z-urqy{-B*Mtg;XpTA6;e@86d@=e6nHvJF=t*?BA=F5 z=b$wanX!hJCjv7$N_C%qQWwek$N{T<)gUq2lmopX9EY6(<{xvs*9t=I=yC%?QRYEb z8FKff5N7qI8>wC9BX&3l5vB_PG>vP@U7eKO^uk(-Qs%;Z9$rgfhq{?K%Q$V=UrcF^ z5m)5p-&PEdJ<(E^uo5RrE8Wxw{-o=fm+G~j0;KNUFwYD~O7-!zu*u{}A{!)_#3(j{ zW0dK9ciiVnJWMnGG4oY}Z8AWd`ls+C-~nORLoClrZ*P4t(eO7?rRZ%rBv_26zXG2U=K`C_20P{>6I8*ew3&K(}`m8{D1JZG9^Nt22f1^B>E; z2gj5=d9<;+P<-DbU>hfD@INCbL^0WhSzqf6j*pI#eL01D!_U|;MoRh^`(b&oxGW?N zf1Qch)cq-jJ^7yN9(x6Xn9-28^vx&`qPcgn5LP0-rbc)tKz_GR>HYbPKk9cZ zKy+P`CuXsHl#DPV%Z1_@PfD5mS!vbGhE1_sa&FAT2~4Lm;5 zFhI=vHg#)iQxi!WOaWk};RR4TR7(sxTNKzD=`$x@V=#;;8oL$Mwv$!Vaj_hOmIx;JYRo31}8+cw>X3$bn<-I5n6S}+lb3C}`IUe8d6TtJa z$H%_u)|3$6kTLqM)8A4_vimOY*r|}Cu--x}#U*1?!C}w%J;E|Ko%nP~tpC7{BK6{P zWGpe^F?OoQ(gsKdx^DA}ii);P7^~q2jWlJ`@KM1COS zxo6_Q9uGMqxmb7J59Vh(NA9#&Lw_=Xv%C6Eoc#V^_xov;gGsj$Htt#=;L-01t@XIJ z{E2>+(KRO>8*{Dl|^DnL#T#v zs+!BikA@`1vgdR5npvn>QmG&D11(Pt|GEuw!FX?T>SsoqvS||cUYN*SaZbFn7AN~o z{Qnk<5^0Gc0G1gwYDnJu$|>*s83f^af$nbdJ*K$WQj=T(;)Nd%4&k>MoBpZ}jAwNP z&knu;WW^KWk{U|*vP-lE7OMyq-WX8Be65ZLBuMx#m`L4EB;pbh3+?$IlFloeGkR77 zW#{n3&y+{)lianTCqcqZ!8J=?>6_`x4OlE4A%rag-Tz8M@ZcicKP=tx2|sWzMaeZ1 zev1W3E7zD9|jx(I{qKIT-`Q(%-KvBPPgvLmI zbKXQXT+@o@!M}{U9=CVO6@OHE6TNno%8ARw$@skVfR7mn{$ zRNLXjbo$0bQ^H0Ong8tTe%Gz9ZNpG$_s(v$2bB3fGEV0S#5I{ulZAYdgj6eWHX-(V z9^~?NJf}~8XDE(Kk}6QvI*EZPn8Os5QW9b&CZS+?;bbQw#!EAhj>#$gS?{!-#{U_Z z&UYU9$D*QvEJk7sb}EMR3U=S54wi$S#YDA-syuT|6Mdi&6_#61A(;()dGV~Fblrbg zd7ZFXt$h#(TNm;~MH4CGa3d;6Ozgy%Fe9%LLg3-bUy|p{tfAXqP%0Z1Ky2&Fagbff zd5MUsQVRRHmCau^DWs8LD?O?1*R3O8E1+TicYZ2$&3ezAX0CTgifK*xA08UX`AoeO1n&~W1ajf}qO#PB&Wy(h)E49-suX+mX#dCHJVZ_c%j_D~an zJ(`u4@!b@c=Q_OVO9$it5?glEw^>z~u#TA3rpe}fUsD!7Gh*`)Ph@q>4Tn(^QBGo3 zezpZAv^@p|a1Pcnct_+iCL|%B2LB$fE>#SeLGRIuWfjuA`{UMwDF|Gek@~cv z!5k5XT%?W_EQbkCa4TtNs;Oghc4Cv0or1jnvlrCt4jVOL1u{KCK-$gIghQuKS-$A< zifRvY1_2k_p>=7lx*tpI3*O?kK$8yzcz~m>C?q^&;DIr*QD|Rj&_B%KAlxa90T?e( z!%XM+)%NZYSMQexc$Du<{Q*dk&1x^F+Y)SDE^TviX!KWvw6X0f@a0(Hg#_qw!b;(F zJLAo~{avxJ{xS6QfD{wW?eJ&1pkPRTOM_S+JS8l$J`PDr)@624;#romSg zMUk-{6(Wk|DCjsFl}yWFR=Dw(E924FlIo*mh?`O%!ww@;a@yak$J2@ zhdvC{wRv*(vyW8Up`Z*X@Uh_+z|R;R_ba&%^Fk_DgM=6rd{t39urUhh4vpq%@=XNkw> z2?720TEfi@*~*&6!Q6!_Rmsk|y}XpJ*J);nLVyNd77Gt85uK~3FI>t$i-zOoxkfav9R|{+p&ureRBymdsQP}boig?*KDh5>MAC`*OJeSGzGs%R@avXG zIZ8dbYOm^I-C*O?5%uZ?`xBaX@JT3G`+4ke14$$^gqA1)u`VQiujyVyW#LGq5vfuk z0u_Co@cUL?;D%CM84|(pu1Jrtgapsa>&r3zbIhRLG6!Su#I`4EDrc|6=2*8V>^+O< zaD(;3_w37TQKDwS-XoZSif%?*?P=N$1eV0F#g8=~-^E)@aT+WXBevL}feDYUtk@3s z(nYAPsx8;5cO_z9RED*w_T!nxJW4&vD$OF6P^TjB5XZU0J3&293UZW-y9Puwt0lGo z^9`k@>_d5wH z`zXB6^73*E7|@IMMb9UlWw7MHB_JL<6I}V0wiFI4hJJ?OYDbWw_~SVPTx7Mumo1my zUXoaw)yR)b-0epsBRums9bRNaX`0<`L+N7p;Sh!D@u>mFnE?}uFm>?FWSw7ZmwD;j z(i-fqjhvrOF;_;#@>i5$=<3Tnh7*`BvTsE9gSGmnbKIK0SS_wo~b;XT}%2>AnNq;Y`ts#*395Y z93+l@bHDfn4U)vv9LCQ_hOS`#+Ax=1Pv?*-;yJ=G6)v$GCnY;}1%wu&qoz7#uFG)TN}cjeeGq}pTfu@k88#3{su&owLfOYlgwt_U2&|*|4e6uZ(uS~>(EEQh=%Hur*`tb8 z4fho-){6LagIQ0=QT;lH_1I%Z4e`{5SaOBMr>+P_6>{62V+59!(rIQ%M5s9Oi^!XQ zwWIat??Eap&8n~34%X-MVU?0A3MQ7%%(+A^@M}Yg5$inbWKLv=IbU5jNN1Rl?q()V zdP&iYm}tRo)E6oBnC_-${%JhWj)^DG7EctcN4kZ$#)2xcQyw0P8e5*CBiw-ynFDvK zRz*okFtxnPtOK8ysFOGZis{@_IPHJ?M;Oehpd<(^kIkK)g2qVefIkHq%2QHGh$or@ z0k*D(yQz@@6^Y*-JUNy!iSImFYjlDtd0C`=YJ#JsGJQ%bHI{E+methu4=0jf$Ojh+ zS88m86$zNg^G}kX<@bW@_Q&?9sqs%QhGsQtLn_Q@|CrM5u3+q`Y6InS1oG4I(SW}} zEHJkYNG9W=E(+k@zn|^aqrZ2V(N};{(favQDaUFQ<0sgay5Sr?%EWd z6_If}SP|kSEs&&|@dujJ9c12)0b8Lvy7R3nwhr@F??-3IeTHpy_TNaL*-NH|=D*b3 z{U1+9`4f9BUVM?no=!h zxt-J?Ab7ir+7i%mQJ&urD#d?*Q>`9rD&j+QdRdnkz6GY8KD<4nCnj3+v^1z}Shh%cEZ;NHG2lu#H~_>Y(3H_m&6pAK zcxm_1?9yPt_VdpakuSp^PqV1!S$|jmYi7y>wiYvMnaDqZs=#pj`}`uZ(T9c!1!xcn z@L^hTB%#({xoqPhxhh|>bPY|JQ=uwFNq1ZFDF@B5FE(}%o%Yp93=fIfnPWd+=HhO% zc6dWEUZ{E9i?l#yCVq4=uKBgqU-*KIrFp+;H4sic-721pB3jU}@8wwIuio@37<{V~ zmt5SvxlLMqCHyQb7Pxcgm7ZOXHlq~Asi`xtjKkJH5NI|mx=>vIr z1b?70Yl{S$hv+E&m8y_VAb4rwJ`n~>K*kDM9Gr7)yr^?9n>TIE99vPXjd|!zdgD2r zy{yf1OoRrvg|+aI^1t3JJfcW2`NRXUPcH}VoTSbv3Md{e9MBg-&_5pwlm+MhMu!@f zQpNvHf|+WRDJ?oj=nL&=3IFCRfJ7h=L+Jf!n9c2>Of28+PiPDUmMaIvIVC)OhD;dO zKlBWUm`*1;W!s3xgRAzmsb$~&Q8lTlTd9&=RW>YfGu1V-KPN#rGa=B~Qe{+$c#kZ+K^Zr43K>lD=-i7zaLJ@_O ztc5YhOMRhq+<-d#*MQ$|9-xvt`q6EN$k(fODLqMt;&pw`o-xIU=OJ)BXi3=7m|ruc<)X`hq}|Voz|q(ltE4CVXf9#~? zh!MNi$@Q3y5OLWl_10QuwJ8a|%X22wA1hx*L0-m3{P7EH#pJE(mLp?I)w;GKKQQ8= ze!xT6(6h}Q<`Qv3)mT(6TiUEjhE~1|Rm{+6IA;F=57}nU&2k%7c*rvWDW}BH5abbW zPia6t2uRAC$+uDaDWVb5WIbwmT7WP?bZADfPsD+t5+q|vh{lu&r}x1x_bV|D3QEd_ zaf@CR?j7KZ*k+SXsL)8sV^KqREzQA=IS035PMwHK0TRVl;9inu7wdMI3oVYr(}Blf zi*Wm32CKxaR@gh2vLpt|cQZ+t;gYNeZSFb3K9gR5Vc{1?-QU2?ICjT@Kn($s6lWPG4uc;oerA=^mpS$h>Zf1F?0M+A%sYJj#9@LLIa3l30~qR zX{)}oqGqubII#3=K4W80iCA@LK&K2PsAzMJ70D6~E~i>8*+S?kN@|Xj6V{;Jk{wDr zZLT>+1&nBa2iey32zJ*S_+(`zX@wgr6bTW3VHK=exekiswV=tjC*xJqQq`-r8BOdPjv(T&rg|KWsf+-;j0{@9kt$F@XQlAHaVP!cCj#vNJi z?f(FEL5jWvHmq{NW=+ltrzhkl8s~B3d<0XTh2OEV#sQXJ2gfbe^2WfB6;jMZ?Ig-)kSaOU0i7y1g22x@ z81c%E$VK%7(;^NEWMz@d=L1-4^TA{?CYH>a043;&x-=b@aCAgY4gb6;c_HjYTsU&>S^AP9Qx-pnx@p#B*t8(wi33q#No6j8}JloeDc0u z?uil-rqQPYl^vb4&+`1FQp|`Nb4pgfX4=G}${&idJ%SfzO!)M(p_Y`J5ikaZT){8? z9x(EU%Kj!9t{H4a4v~BU!}OS@AEMla*YS$F0Gi-gm?2=1_-p(-L1n?_G7*M&1U1$; zYRZb{Nf#xIG#8@B=Od&jfS4%b!muABzFFmgkVl=X9QvYqa5_WUcxkV>^m!x_og!lx zYby-O?ofxBkgf_N?%Qa`f4;pCKX`vWKDNVxx&i@C!fChF8I=UxiJ(DQsWX1-pdY9D zE0#G2aJIs2N08i%!6Na zb&4!{I%2-Kny*&|hSv;X-X7O+oZ?wN^NU@EpwmNdHqLm45w<~3M`9w(hQ+hUtH=CG zu2W`;5fUWgd@QCYP|*axE6hw4p_q&**^2t=mC%+D83>etoGOQRi^s!%BqaoY_xJo39_KQKWt_wi`!iePv` zkDAIov%cDuw0Tnvj0 zQ4)0?Nn!+y;hLb*P#+(a&WGqy5eY?=g+r&;!DOC^twa?CsyIcdnZ=6N23iYtTAk#D zGU6d*CP3#BK`62iz20UNu%X#Cc#xTqhutZBicFLoq#M}5`&K^bTI0_dOSQCq0X zpeQBeD@^P=14+$U{YtGj|2%7s%cUKlQcqj`O3%lb-bR&t&7NCcbRNyk4Y+ivJ)u5F z)5f8_KZ>?q8P(OxuwbF>ycYYWRH@^qGtq>i( zgZTdUAH~6g2hrQxi;9YJRNqnwm(d0(;?wl+Nt&8Qxk)$ESkqjZaJ<~qhoYh)jE|2e zRWs;~=$#aCX#|9TskDW9-}5oQRLZjUp?SS3B!$bR9Ws+KE{FMO)#KD@94~wD=9|{1 z5iq*LG!Tg3Tzd%H)>z*Gnz&-e&)c3Q`jOckj5Q#*UbUYUFE8a*< zkkpi-__9zRu;^=Kjn^UzYKwQuIh%pU&PpBhybU*0o6%e(%mj=j|CrTBbKcWE5|^`6hhp=g%c|M^&&9 zPXs5rgSffb29tqT9g72UyH9H6xss!#^9hPjwsufEuYNx?!%isY<@9=L^PWAwbNOX_ z-{~OVn+w_71fC~ma{(_L6>#TG93fycbK$i50kk9Dr_4!x-V14ug5KG`3+hEelrXc+ zs`!A34E!z^D_x#?E0zz!(^EfU}?=E=kg&n;^+wYW|M(>+`|DaE+jst%O~1lEr2w zrkv1>dP4{pja#KS6O(@;u|?dElB>#+={W4cU7Kpsn~_B^5{aO#?J|a}&Cr6(3-E|0 zL{m2-~n(9ClQ*N0WhYtrVV*Bj6?A)<3Es-&_>ZcBZ?vJnB~MzS>9sr7#q zj`wNjWzBXnGz@=QDw#$d+KbgJVqIeZCR0jGFk*%jMHx@NG_#T9Y9iiij+aITlgSrF z&@atIy_aSROlFhv!+`G4RYJL>fDteTh8(b>tSlCbL>AoyNxqB=9FF`FFfd#r=qv?M zq6);!pTuO+EG zIXQu|Loo=}yyS&n(8Juc3sW_B<5_nDx;?z=?zOpbuhs|4tdp>=Qc$9!C(cQy+*29* zuMksJEV*r>ASLIbeq|zNe3rS+4VI}7WEdk0`BEJ(rCy@xQPbZ_`CM=?*z2)!^(NHS z*CrKH6^zCNJ9j09@hKIxb}r&Q(yxO{I8KC?<9%ZLkbkyELcnMYFq6rkoDYYi%I1Jn zFapM)faADV@ooCXhuvXdc>ii|dYHpl4=PHMN z`-f2cv7e#fo-aeU=G{2&w&Rx}qS(-Rz0?uM zI}E&mo^kLl-Lwm|ibHXVfWk2?xV4 zlfNfoj}(364{WX%=7i6nK$c|=44T-pXHQ%(8r{4g#ARs_%`XH#ucs6Y4A%%jeQDH! zu?Tg%4+Uokn2D%i^fe~Q+F{Zwj_jd`2!rkw{DxQgrqPV#&Shw)QkJL;nfN$1xZHS& zn5V+wnd?YQmfhFehhy%|xT$6%Ot(D3xvssaPUH3F{-M95G0b3_HZ zT@pnLU2iOQ8w?4~cp~PZ} z&+dYZk;mZhATD)}Vf(rg9DeLa*n8kIPM$b1AIz1SusnePP7au`tXS(hGpJu0Q+09E zSYD8aeKs4sUY|k;Y0z7md4Q@VFL%p$-wqjim7uISZwSbhm~kmDu0}OW>tEJx!fEAu z)M}7&O!JVI{4vgUxpCqA6F71FI1aw_5<;O+TJsr_O;)to``I@b!l_F-?B1&OV?kEG zSIIS0=a;H}c_&1~!nC#yawH5(v2~t+MaT~T6a4|h31KH^oKFgQtxS-d#1xn73QM7Y zaXkOJHghhkU+y!Rj9x4c>LKip6Gu)oz`M>P;55 zFfl;}LUFuWWK1`7l?oH5Qm2TlbtT3yf@Gog1^mP$6;Pt)(?vSq48O*@9l zoKnfwoJ7UR+V?mU*~_GUsm*!*Sx&w-wJ{T(b-pJF=?W^ODiQQE7$Nu1=l8+u^D5*k zOcW@pcFrV|=M?f47Zb@>@^#Fg;j$>2oVxE9y_asHfJH)t)%E~4W`SY8?B10z#%TJ%aKr_vr z0t3S}fM6}1j(Y}TG`aEk*c1wi@{m`Y4?Q7Zv0xZ7F|AMqj4o<=-Bo;bBrM3B>Ov={ zFYc*zvJsI4n0XN^OHHULw7^W}xoepVH&#SZZs!Tn;bGE+lp(8h6R39@afVOMEoday z?3*8)6m&-E>;M_csWo}Tp&e>y^E`Zv+7zDDQTTQ%@%)6=7fO|HWv8qysLfe9@ zH^1vK%eCe@pZWREmvL9oPGu~Ob{UDP8rkDi(i0^-yR0GHw5g!J;{*-7@1(CjQ z^t{o)!AkCDd9e=L*BkJTTMcm9X`=4LU>yXxspqSn#R2 z(eAP-yD`T`CX~++5yeD7mZOOq-mVn^o`E)_QMYVlc-+#wvH{M*eB~E?a5grWKO`zi zx%Ig?;$O{T&gIyTmU@yXa1g?@xg?H%yCWa9_9*m13`slRX4?x<54J8}h376#!tGlK z_eXcq1;ZRp^aL=t%8sgh9g>wJjj=PSD70Sz*j_86tucg9y5Xb zS3;U?e)H$Em{T*7v&{D++m}9<%ll4X)W@)`Wdx5}E%5snA_CDs!8D9Vln}7m3OzQF zdwJUp25eg=U_SB#r=oskoK%Jo7%GSaWCXn;WJwRnABMTWsVHC+Lj$9*+Nl2|9}+9- zlU!J?nF1D<?h-7U#fAM?+ z7#OY*s&CYLhkh=9&tx{;GCk?BP&10d>41q4FvY`}`cR1yVpr=1mQDS-iau1&s}KdV zAfm}BsxR^huU9y{$hR4j2$&MiK&MCFR17BuB|^Zo+pEos%TRYytqB`yjD$RJnsZZC zzjFPS)@&yypX9Q%(<;kyKQ+rV`j<1dqrqsSsL1!Bxv2~%PA?=irz(>m=)e;t>`&fj z#@)LODb7`?F~1fFBZtg$TIfeh{hE0S1w@2{v;C643A5d<_<&K23{9Y6Si@i{C%hBKkDEraLq*eCgdw9^9V-b$ogAEOX1+M)X_SZ z@SJnLMx^({amnp%kwNUaf9Pw;>XaVrs&TqLTb^ zQupcnr;a71vr{EtMvEni#RU1Bc|3j#7_J-meLfRWbr#hOX|dWCKb6lSW5e2wJ%UcR z*pB!*BB`(X?K96*gMr~1LGLP<)awm#tIYzhXXZCYUQynR0!A~g5c8fl5K}@ZJ&)tXY0-dYQj2aaRys+6ee zM5;0xjA)+_(LO$__;JWMH)NW-hLVzYT2-l0Yn!E>Dw&v-bhxVsx|()gBj_rxqI}KQ zQ&GQC`%S&3q;nG1E|bt$o!mL~1EcRz|4<0e9}&~WP6|7bLH&}ot`{nEntcut)1!M- zB!346NQ8*dowIp`Gq!5Ffu*=4pOUe#p`vLrwQE%ZX0_NBHPR$iTBfEZ*f#s?2mznZ zNZyx4^~GOQQ4*SDr&L zK}LzW(Ls)NdIJ!r$?iBz1x3WP5_4xFC5d&^7GkY-xeyMmHVJh(t#V1kP0h~aT#Zm9 zX+%XCXZphAnzJZ=qyewDQm5C<^P1}%$s|xy5xN@Er`9f;`UQ>t)m~>XJ*xJV(uPau zGiPtw*?#Q$K`gJ+!)#8@tw=XaM4}uHo+96$(U~ON%BZPfCy+ShEHS@QcRnVzo1J?s zBw=b;oMCU|Nze;$73V8ISf-~uaOFFxcTam*Dooo!uS&pdw#D_;p*}7X6H`twTsQCq z0;a`uET^!WU;idZiuLQ(UBV)R<2XZMe&LoYJv}TcKEpKuHJ2D{mS`R!T|s|{m|21_ z7!4>YF9h|zr<#qAkgrK!ZXPRF<#?ZkU}v8^r16db3z*}$9u)cjr`-ACVvA% zJY-^iL|jyy?;Ye34n-6bWNBF;vDnMstG@9qX+gZz3E1K*U|cBZH-q82K|CH$b>V!? zVRcyF5CrVax7=}re1-?GxG+pjPp&`k?6Zu3FA{UvjgFz zK{$gIruyA*?*1F(?fD$U6(7Nqmw8NERzee;`s;b}m0Fey3DT@5r;&%N%J&GUljf9q zX+c+0$y7=`nbX+$s7Ai#?$7LVMcxpa8j=&5Qy9q)gb`vYK6z1wOl{*TL06N;NGOw4 z>!g57j?*v2WlRjl5DjyXh$&JgugmKzh)S%RQH`T9I0+f!1WSl~hSD}SsuD2s;yX)o zF;QI9#h&5%gWdYZAYdz2G@T`X*lsK`f}xPp;d0e~{p(K{!N710ppQx?WC`D-OAd{_ zL>INHhHB_d#0(jU(MY8jn52GSSxh;qWwLge8nlQUGK`m4mZ3PY&?N-1K5rV7cqW4S z_RwJJPh5t=+;n-hMCtkq6usxC$a~9wVmkju{P^i}`1l`v8lU;hXYjkT{>*dZX4NlF zdoIW}->Y6lIb@7@uhC>-yv$}yS+y)V=32(jL@ zvB(ev!M=CzUIQ4eIrho2j>zkDSL&krfH`e8AKn1C@4oxQb!*lg#$rR3%e_9|d%p9X zzo`KO!!LW(bRK#Q5^5jj(beA2?57{~#!q~;6B* zEjQnSFZ|O#F@Jt4YUDquLY5x}3C}eD<9MG8DWU^HaX1Q` zC?Y0Ds(g(Mk1L9t&R`rX+w+kgs6c%eq}{&QN`--Zkn6}ZGecen==#lX%!Gi^MSf8U znCT7Rgg=L-#-;=0$&W?G@bGYBG%BtH1H&~yN!42-rhL~az249_N*0u0Fbspyh~lbp zWrd`9Az{*EWO~+XMPQ|;Q(%yG<@}ribNGJ8+=3Onx)n{XZO}Rz1bww40D*d|T^ckk!TR`3M zKBe_YSDYwZWZ8_&m>(8_v0K?37Dh6wdhI($Md>CAixON zb%0>sgxzQ~E_z(H{KCQsyg}gcOr0RIVJ{XL82qCp5;&q{QS{mxD%|Oyo<26qv+mEGH^h z9!(;c0P2WuwOH`f6Hnq>4?TqTD_2yLLsKH)Cu-qyCy3?AT%ef$=ot~CQ^{SYz0e?8 zTn5!^z9xB}hdXIl5;8tfym(^%EUl?f+#{!^Jn;Df5cIl}MxEshG@werYOAWovB=Qz zykTHq+zN(kj)8%mJf4_@v4|j_$=-^Fh9SH`&@(kP(NJ4|8jBBCe{b)`|NGwen!v!Y z#Gr|TB~A!d)KvJLP8)i<29@)Ud?)ftW_Cl;RU|-u{f~KOcSB}XXXM-nSwb0?tJ;X{0;m;}Jby((?|_t1#mmX@er|4w^~uM=JsyX9OoSXWK=MZvwJX2S35onr z85tZ?@;};b)?&#!j1zXZsL}8VOSJU%USYvluLE>B=-U?`|4Vzk^yEK{*?5Iv(lrDINSfnY6xv1T_M zd%l26`5(t4S4z=E7V@ml>0E~ESG%4hXL&C7cByP zgs~kK5nI*@Nv7gClI-`3cMLQg zT9x!e!-Rn46}W;$6{X#tk^C4mpi012t}L4*v$%pqgeZxYbC)iag5jE@r@t#N7LPBg z0w(Z${K1qo46kSG*|R4;Jlx-Ex7!z8EhZ4ooj-f?$3OljEHx3sl7nuaH=Bi_@`^H_ z!JtQP*8ue7xv;bVCJP}afiNVC3GR@HV5%8XgDhzehO|XDW5oOP!}OC^P3C47Vkw55 z%WOoDSXd@0v7)J$D9Q2%gK&Gj#MIHpph2qC{HWv{+Nt!NtzNF}wCbjm zbJ^-5`SYL?B3M>2j`FgUxNU@hQBwBuX_=5>`Blwn?m1B{i^XJ&bj1*hnw8H#O*>Rt zRYuJ6W=u^^Bj5`{uM?iK=jHvj@lXF$Q_NCLh`nRSju1~Iyv0N`8ns-xe7OJ&*Bt%* z{my74vZy{_MTLbELxY2OBjH`|de`uefA+IulmU(#maac{d-10r< zu-GOc8v#%wZ;8d3h>b?S^}2496*@3F6#(^t6UDf)!z~(1UQ=yE?pjr$!?IEX)>j*` zqa}|hgmustx4>Aj8B*bT3{8d6cCZzP4;{j>qes!#*N2IzNt`7lcHC=4iA%^lH%-Er zp}y*kK<4Yt;r-xL?sY1GP3>1x{Yq`4^&YFvTS9H69xY8~3=EDa1ev~1agjR5OBfvw z;nW2lH*V3Z&Ph}KN|{&c6-^Gt;hEMG^@}6s#~2(g7wk0N7wLffeUR67lvS4#R*oRY zY1@8vS_LMPDI5teUNj0K-Rk18m}B3*eLAWpfZ>{9Vtm|6e!VT~hKQ2V(xEpR0V97S zo@gX~Sf|t95s$~pu!tbVF$w*_~vN9OyK?S9V9Kk=k;K8w1hsbXbrr@HGg z^`6h3%Syhuet_uUs21go#ArZOHQ3efQ2xMJd|U(ra+kY*()s~ndw ziecejPwu@iG0juPfYpzSJqcTZ`5OAbV~67D=2b}TTS|N z%kTbZ#!y9?3Rr1bY2VQBqAC`Gpcm@To^7RO$VDZ44B8kT9xlqy%i9zP1QyjCTvAkY z8E-)R_K`=9SnPI6z;4GPgM6`+O-zp8PlzAQMfo%s7?u$F=AG?L0q^GyzjWfUzV1QP zHCCdkz8WRfCFs7`1vwIhTM*DY8iK>BCtvV$Qb?A-mKw)grt(DfORa4JAAIl0Q!*7a$0UuSeyS^k z^Fsz~sZX4^#(Xu&kecJYhG{PY;mkx%RAYW6j-Sgsxy&iY81aF(8$rWz2?;DGy>AW2`=ooh@Eo7@{Tk`jLG}>~A$grwS%})@4N8`X%dK6M z_)RyhXnM$5wQewz`H@0X0V^*pTT~}}ibyC_cE0s&9vH3}jvYHz9E-o^Q*S5 zo7sgHj#GIE-IGxSBeSMD4#=*8q#tux$XU{%CLzgfJT74|SF2l@ufu=8Cm%olNIu@b z#kfGeQZU`|5}tbWr#N@^Oitu$4s@60ATd;(?GqtMDGPr#B&s!OZ8G>(rJhSWmQ(uA zaV~R*TIN2L`DItX!-{$sO$N|F#Uq2Gu-R>~($bQ4`%U*{-JqpO!0dMC1@g40`R=@4 zZ^5NYm)Jsb4RPkonL>}pQ;tOh`EnjReE9Gi%K?$K%7$z$j4!;>zx?ypnt+H4#+-d_-m#bI)1ib5OrhUURuBH94Hu zOp%kReM%kbJ5*q&X^2vaQ~Gw9MXaruNm+C?p!o|UF$w2;!Ol1r?;b_wu9=F~o5cQSI+;>WUT0vKn<}ypvr-tL07~&xl zv#}f#VRP9~L)0%yoO_8X?DhIlQC<47zNkE>n3tLathM!gJDGq7iwI(`HR%Mw!QvZT z8_@e6lcc;*Fu15Oz#I<8wBU5UVK-Xbci(-Xn|AGbirmj7@pFqsqh+maZGZT!Z+)u- z3=B(%{9EtyI19_K(CFiX{i6s5LW=rTx1w=op`wxTt!8u+Go&QT*%cHmLZMckP-l*3 zsO5X)5*JoZyDv^n{mM{3sa)l}34Saq2%xOA7*_-8t3<;lTpW}z;YVhIsX8Au)hx%b z7FSuO9l<^&=qi^%Uz)4WsVHSyWH9yItYyy~D#4^%NShM0-dC;boiCS>W{OUz-`^^d z?_a{igE3-{lu_MO3k&(Y`w8(H9vFipN@!Wz{Aj_=f0$EzNKFFP*Vh-Ym`ouoB8Yvo zxV)_5hR=NFGmD-Ehanwb{pwdu#YH6>$QyBW-xybk!h)i%TefXm^aStM5;fbm|I%!= zj$mnEn|8Zz{`=2={(dkpEHUgw`A-)W=RG+wHiaQ#a-q8es~cTJE6PxoM84F@IOMczGPS?7V`$XN)?SuSm&ajs?bYp(nTy;$;*R5FR|t`~ zq&?@v@w9Hl)#iIlDpNOss)n7IM@sPBOr$j<`BCW?NK>dd!46~o?a)>I7ry;i6AqrX zLX_on0-8$hlE##^=L>c681zW!xgTw>{NWE-N}_83Viq)beV&b2+$7vlonC0$x^-&= zZ(w}&Fa9F5aqarAlP}XQEDgwe=X>kQb?g54!3Q5Sfq`L(P*`G_vKJH_GZ+ot^JgwA zDwwmtg@!fF;E0+dPx%qGns9j_h`6Zk%shXbiQI5k@jA76mhy$N+|{r7Q)+XWMS*S{ zYf8hgTCYx1pk_#c5V2pMmf;Q}r}-?L=MpBCW4qL{48$qdi1&$g)RJc}Aj8hbRI)`g z2nc5A%(XBU+zDsnmtkM|G$PIi(K%RxOP9y-_;ZtJ?UWMKFFC`#0<^B-4UQ&UrK_~4;a0pEUCUVb|{TvX+F4v}zp z%|Kt@Tc6#xZ!p;7&oYk-S#Xp0?dqx700b&#@s;tO&UR_v4s)7lGgk2d5V_-6# zl{|8S9)^N7Fjee=V5>|h%iwsQjg)3`yyvpItY;^^31cjfrP;G8>X%@ugu!(KEEOMv zqyC>D6+VdbJ+=7x-ly@;|MXAz#794hbLYcvHHPaC^l$lNd%w`vk>7rjEIwP#pS^5rSYC^Ql0uYJ zml88g7i1#igbVB#AOx(ysfURsM$AO8QqOZ4>S+*!`NM3gkJ{@@T2z|i{=!-W%SF{P9kbuyYhhYlR zJx=l~yT=KtkXBty$9t9jb8@`r)a!G+5jtxVboSLSy0($)ZNb2(j0*=Y;ppM7;QaY> z=xFbtnRJvUdYv9#Zv+>wMBv|Tg5Abx_MLbpC&&BQda;O%u5(d@Ld3Kj^g#|uC}}K1 zesR9C+m!}hrJGUg`FRH_OAC+UDxhh4+P{ClBp40(x03-!(doa zj7^Mxm3)wwV-ZnYTzu%xyYJq6^4PIAOd@VA96EF;wr15TF&vH7`2GF{a%yq&dCfpi zz61(fd3ol>hK4f(0|QHzEZ}Pgmt_niD@`*Wy6F7_wj3VkM zA48J?LBcL*U55u;2HVZo|HV1Nh#khU@aq(pV;eZa(fCmGMyMQK$zrlveN^3o~jjfVbZ zD_8t?&70Po`|5X|&UwQbpQ-SMtvd(uUHOY156tbEu6W>qzq}C)ONI}8W?qP@NSUPAod|H)5&aw$k3!|yq0 zWci+?N2T(IpzhmwP@rl}6q%WIT{MfL;`=5*+qq`4DS9Lp0Hxp`=)D)Xna z)Xf-nB6acAsFV7vO1{+U&s~o!;l?UA@~jIg7A0IVIZw$#C>(;v=Y_}XRgUR7VnBn{ z$f3GOkCioM@Wy=T@|F?O^+CAa^lcco{U^pvH{pqwdhn-z{yDt=5B>l@diV!~l$^wi z=REL>7VZ0z?X`yKF{4Ah%C5(xvuW*;O^=*l1#c*ZG5;nwn*I^4HNQgC^+#y!FU0@% zU%$e=@Aw1!!{PwyWR8s&)v&dJcd9hs3b=3AC40hj7Gs3AI~8mdrDKIdc>pr3m&CPpk4Q(IYM>8Z-?pT4TiX1Yv; zcir{wffJ{Xzeo-#Ia)L`B)Or>9{KezKXl^6iKCk~ZDNUr7a7EaVEM*3zxg(L-?50$ z>-7*F_yKpwSB0hsAPQa z-o3xNk1UX2U|2*n{=r}N@B8QXyf`#4{FeT{k^0W|J}hgl#i}i9G1NJL=}8adxQIdW zNgQ=YQC&Ryr@(1+sJ1|IS?VO5QzdAs$l!RNX}BDS;#}X>P$#ymU5W0YQ%a1exRS&> zqNK`6O#5cgaj3}GqrOCsZ7cF{_s(jRR=2=Za|@*W&2R@L^!D`NiQheh=bwEZV`B@^ z4XEi-rxS4cVlVop8?hqaNO(>}W#Sshc7M4P(_^M~iS;y|IbI;dvH*gy9EQ9dFcjW_ zkX(j=k#QV*_8@-u_~W>6;X+!vCW@JRM(^VciH(qZNr~4SByxE8R1|NzL8q7@v-zv3 zkuo)3vB{x0`Y!7sMn%YzQP}eH(Y#>=OcoP{2glIS)Wy_xERue4mPp z1nmC%@AFjG)pgN@lw9nh5ip9e(b4T+{>oQqI?}6hVq>^^Jo@Nw?(%uPJF&PBbvpgU zyYIgH+*iKx75qMd5U{>&H{9^sQzuVuCF)comI%b0ymsG<`~Px$d~$N%KKX?`dpMTl zo?%h3?8ZI&+fH46e0X5wf%Z#XsHiMac7`>sYr*m74ny_^X%thO=?S7FPYv_MRXB~BgI*66W@JhrVW z!@86?i|`$TS2T9X+u)SeVtB+iHS*^9=;Kcu0a@i zymsoB#x<&{U!1m+KBsp=Z(j+cYXfwSHIR(WxZE+0Q!gA*u8(|AVsKDBPB*=0R9TG^ zvK1r5i;}OTgy@98E~_Q?a)k~%H|t<9aH^`L>dwcx&x6X`X}yqN!lff3B0(eFVMU{i zpl)S7N-N6{4o7h2#6>~^<58>KcC>EgibHE&fq10LR$=#>-qiN!FMoNF5HPBOEn2t& za--``96NT)4}S3U#Seb)wg4Cw1)uuVr)qxn*kilMVqK3#1dW5j@!Z8*Zn>rR_lkg%EGK{|oQiV8h$S!G0Xr4CJ{dX&0& z7>X)jUh!V^PV#u+$Is);>C@=!=uk*WHYa`>zJli>c;;Xy?p~1(BZAuVM9Q^uuO#BV ztV*8K9q%~^mO5f$+yX=XHs~x(gu~cy{P0;Ee))fJ`EncDue8JOSNGJQ>K=8pkBPIS zizr{z>^KLzRlw#odfdF7sE0KI8ftjB97xImx^O`nj`wr9BopVJa83PfQH*ryAd~lx z#{Du`%~&=YYK4BzY3wi3I$T*_^UUgxeyIl^`&V2ovJ$ZR%E~K*dD5-*+pvfPjNEYJ zdvEJMVl$$N$m-AwK?% z8#jKxufO+ZLPnQjN8}uYNI1NwtGz@1#y7t459IYpFfc44s@JSMP;lU-i<9G1HJw*_ zQC40ItKEtfn^xn<(+7zPMt)CM6rgiDfEu!x*~}`-j)ua-WhqyRIOL{iT}?TcsAgrT zuhBPM)XVHqEGw3ASro8ixe2$eF%kl%Q%ILd&&@CRVgED^Jo*!S=dm*w9vXtr=Tq-f z@qLnK@@~#zE_}tswss6gZiB--fUCOBx${@62qu&zg^=I`7+jlRD!!GN88<;NRiO3C z5ca?D9A0|qMGOuMVPs@jAy{hHM+qlY3@P~%Nu9)c^nI=%rrJCA7_e=5M>OT4Lj~_jB=+KfmG5@|`(~cdh z{2t$5`Tah+^KntL59svz7r*lF-~7T)e)7FHbOiiNxZ{pHCT(`7Zg6m*o_x71WzJJw zEFNnb8X4L1)_1&P-+S)8cY^#KUzKkH!?go3Ve3y@e}XJvL^X)n?TGus#1yF`%1xqtg{xD) zkgRlMOgW@wddyINo_wX2slDds>dR?;TZldI)>Q_4bhiz6Z!n>$Ob3^hpSkvget3j1 zMAVdLPkZ2Y&t(6bGgr!(@gEBWgYXCZiV{S=TZ!t$&0agFJZPE0UWT1bZqi81JnuyH zEA_r!jrv6|gEtTpqa8YH4a^nqfNS+vA?3XjlfhCv`SekI;S2wUul(m%XwYvA4bG6u z`D>efrX-8*0`(I!YjD=7o}QyQI4x!l#rb;Nu+fBn`>YLr`3VztY}BEqoL79kcwQso zJ)bb=x%sMG%RG7H7p_YZWt@H?itbkOl^u#e9uFvH^_%Y616~jmzpt~WTIqd1w&uni z|8?u+Bp2&pne)qe+wQIM3FVB^~VsdJNCOkJ_ z2@#7%o1S|7@rQdlJ3sf(Lk}Ie|Nh^f%@D6wyyY!#$$R4Ir*H7}_J81ar_XHOuy)=5 z;&lL>gcF73CHqDOhL)c{bH!X;SBavMd^D_Hj_I)}grT;u&msqm~vE2 zWQpV}=^%&K*_4k=^||!ojD2eIG4rS(_ha2k9oDbV zgzP+~fs@+v8ZS~jnS#b(9m$OJB) zzYH-h`par6&WESQpTny_P6X_OAN=6h%9Sh6w_Uli*aVE;lsu2u`+<_8QkqTt=U{kE z(ACp(cXxO9yRii1i+qSDtE#Gg-FaovBbZ$G_}bULIQrSY{fCEx;o!1RFt{2^Ov0#R ze*5M2&wl6o-?x4K^PhkEAOGyl@*?bngiG{cEtuD)noL@Yc6a zTRh+Wjd6VH&QLJ4y!Ao{3X8WWIU+~hx#s1RrM>O4OP1YYb`M?Zh+po27+@f#yu9C zI(P=>&+o(ebLSQRwZz?ti6cscI8tI6n{}v9B$jmSqI`0F%L(af(P2fS4x3gJbEc77 z=z+^{9ncOt!EtJ{QHO6z#+4HS{BH6!Jv|9IAfckA3N=kN$`1w_baisV4Wr4>S6Eu{ z%X{zL5WqKIIS0#$fKl9h`|Uq$y?ptj+#)A#rXUMdQ&(>nu|$5n_1oY6_Bk-TD%^YT zy}O=#=9zoRVIh_P-2= z>EcCwJQgbGua=R=-7oChciZ&zG~Jy{T|KTYm(4W>-R$ww zm;UJNWKY*K(MY7KuY1rkHadaQvLZBZSc!p7>N69B6bNI|Zbrv&1Z(RBWf$8#Qq?aN zg(IWmJ)mNGq>z!-^q5+lL7B@$W@NQ_X|`Q>t&{w48jOUL#FbDLN)hSEWficY!GK%W z8BkZMLp@Ore{-Q2y}#|FJMiYaF_N}4rr5#L1Gu@V1bk#DeQY2r!BjInQWK*-Z!Jv4 zdx+xI3{hW;*311k_^W4d?(A8#wYDkYG1N8;D7zR5;fhk?6_3rUUvr@5*oJBYZr-ZL znr0muYXnr3(A|v*^GP6ITI$z)u-Fv!OV#w4dX2N6m1syt??n-#{btC-E_|e|hO|FTXwmO^#VU*5udmemMJI!-;sy}+@(8Tv2et5Un>uti~!$AIs zD~5(f%>VHBU%2?}vrqnBo3dUF2#MYK#8Xdy%J28xj3rQC$RFImik3D1{`Iea^~A#u zKm3MIKa>m3pFbb@$o+rTeeTSO0p@6ELbF$-H{ zo`3U?fBfUWn|8b39|#85VkX|=d@$Xz(z0iVh6WGeb%5_acRb?hIwMXD4&?^}!P;;r ztgET7gfq_xPA6cXy${6h1lef7B>4%Dub1JpC1?P1emHZlRg|Jv6!BiIJYl>f(w1Rt zsFZOj?Q@xzTAAYb9Sh^7ivgPJ8O@bO{K=hmeEM!1-m=Mnb#;1_OQ#_(UqSlT0h&m-; z`TAzGY+OaEad>I}af}R((|o6WW!2^XTUN5;%)|TlzpC$1?rJLU+_~p1$4(si8u>C` zs;%`wo7Mi)jT^Rp>86{ucK<%)6MU^e?v;-Gacq42$tOSW^>}t;X?{_Q#YIKWmlPNO z$(b`}+QE>7_kQq$dmelA(JvDvY%{JQTn^{sD_5@h>Z(=E$Nu+!|Cjk$E-~Kz_O};b zxpHN_*BAKo(C{FQeW+S`Fw90t0 z$~8c_VKhi8Z!Ut~wGQU0cOcByVrY0&iPiPO^UveJzWvG=YM4u{L`{t0*|bWD=0%f% zLs^kP6fQmPxWS0sTLs0zK8>u-#pU7>m{A7urPSb3?`?MVE0KWFdY*9+&;MA)bVOA z1qJ6vM@Or%G`=jBU@-8mixLr!@4*s*mN&Yt}gAzw6p+me_wIG&%( zD=7HYAN;`|j1U3_hGhKY2S31blxwl(p@ zw(Zl;d(QI@-u_{PNy*!-8lT&-6bM)N4_gvhL`=yBp(u*~6qy`Ph4>zsof~HKll+ZIy zH1-JE%M5vKoBr8Z_dl!2ubO-hdAXaONKZB?pu82@VTCeN3Pcz!wM;+X5)Lg)}2`QEAIvq;id@$+a-{v_mM zcg%I@FcPzy9KD4#YjYeB%`t2A+c%qJIil7X>3baTB{eak(UrZel-^Ng^JJUs2Lee7 z&pOdYB2k@aqP4BirIXTv818iAk2a8Y2CefE#O#SL1mUha@0dCtPq*^Ug>mmQ<;j1! z!h0B)^O88Xclzee!jN^tw5W}0(+tO-G*wt!$8fMcPrEp_n!>|c$rM7t4u0}UHYN~b zTf%T>U20X@TX+$oq`Xm}+V9-`;0tGs=0nV0J8Ad<7CM*z{_|U73-0Kdo!nT~=f9TR ztxq%{B^5=l>%~7T{Z7-6lI5Qay~yTx;`?+!vwfntl6`jxiCdJ<2O~ZdBK{TVD% z?K}^$lf-b~04D|X`)5kk#YG#t<+QrM+vJ+dTJuMSqLFjzN_&$$(Y8Ta&vQQ_iYxv% zp^=^^-Oj^|6~6eHgY?}fdsYONevsKk2Tz9nRlSZAp=*h5prYsxS3H_Ux_mWuH{5`y z7t&zGAo|`wm_6EGJZoFjl7_fHAa>~;-;NU^974V!U2U(<#R-Udi};lY=D5b7`WD!7 z$#1igHz)aji*>OS^AV$WzxG6MB1djja&_*D{OiNQE(Jw~hC$j5aBhzj)_4|B#`Yy1 zh~^TFN5c6Z0`3#D#;MiwF4=c1r(pLAyD?2bx;-s{OSdypEwa zzutDktTm}ZT4FrPGY$l$*L$>Ln zv0%{Lwj~{<&q2P^Vggg_7ZLOEo2pS}Sua*l{N(ppRrqSKeY$Mm47U;`mF`dUxXZ*l zI~8=|C8(H7<ygr=8QBhKK?K*OsGqt>RBE^OW5%kpWKkIZ? zS6ACT%n-jm_NUNmeLfs!{jT=h4uCzD9%BaY{<4sYC79bm8BTfnavy++#%7Rc@ozQ2 zIsNS|(t1`yoC#`Q*~l%DTt)9$PSW>nlm&uxx8b$BAq{!>gdyET?AKKI+G>r;i-Zt7 zBf^1HY&`IiuI&kfSVk&qgZ~6mpYhUI@Q`P`UwrniaOj=!40y?)#{O=8b}~B`azg7@Lz+-(CaeI3gTHusyo@%G zk4M!__V_019Yf&2d!9MeUOl(WzROdQz->fU3s8Yswe8h|jE@I`Ii*gc{ct2nvP~nd zCVRjPB4b@XcnTxhx}Pxmx6Qz|Qx+25adUs=xAn4mlw0z~zlq*yb2I@>F5PLU)VylL zlroV5(qU=df9K5U-WN;UYJ0mpsbXXlIzK*bNAYW$47)q_M!SYQ8Jn5;nvcC$+kzcW z|Ni}ZaP;tHdvGDe^w9%T-HQa`F1>J90`K^DH|=KA z{##t^$0!t;3Yw|=fhS21y)rz<7n}jP@=Gy<=(iI)NY-ahFgE^G4ky^ z-P)g%nv$$ad56YO7YcUyVe|MIg@h{CKp|$_f$^g`n_aC^BIhjtg2t~y&uW-UVzq6q+b37roQ}}bM${q$&*(}fibfFA!7U@A95Br( zh;2SSbU$|DKqV-L;9z~U>C!rxcB40PJGE*lp9-P{pU}XxAd-9}3?PL7p~*x$of-yy zL=uiJJbNBX$y?$#PL~h=lXbEgipw=i{d->;EgxEsk2ezd@CbkC6jo>wBe-+dpmKcd zjwG2knOLd2Q1ZKrdjSJsEHNKU6F}E_#cbJx>P4?mF-@6<137s@dxtQ@ z;?@pzIEfmd%R|%rY~ojOe1<_Anx4K)#`{En>fUdSJMe)gwl2ZzVB&3n)qz{eOM+EA zy!%aa8vvhNZ3xwXJ%zU3wI@}+{hUwdxJ9N`_EkDQ`aBQm_vM@%!P!G#^qQt)wwE!@ zwdE_fI6u#hgYTh8?HU_2Y1eYl*0niwb@gs}Jk4i!#p8axO{sS9HjMw9$=mGA$c`P* ze$}G;hTR8^Y6SI8W;;GX>wd1}=h==-gJC+6%9vl0>)U?0QfGF;>70A*^qrP2H_6rb zC;8M)BXjSy_*levlGW4Zo7h?a}$6^WR{c7dYicRwb$bS!> zBS+)u#niPI?(4a6(qrJ(v|-Iu2NgNQDO-_?CdE-&aZXHBmaO$$kp@^CirCn$6uT-AaxkIw7irY**HFFY(fH6Vx_3&H~ zB46nvQvL&@q_DR17(}48JDr6Q`vM@wgFW6ZT70Z)I_n9cl~i*VGdXm`0r6Wv{+io2 zpH;;c>zfFS18DYQrI|Jm>t^%zc+o*2CI7icd{xxWUmc^Dv*jq|ad5-OPc#G5vZfJf z2cBWF3*2`%IERS7{){->3>|pG&B|xTsnN*XxJ0GfuUJ5sr8?~m`cqj`g4271a~Rba z!U7z+$xCI2Oi~c@zJXx*gmMRTn}bQ>D5#vt55CTpj<~=1(y|Uq35fZuQ!a@HnwaNgTt_rUbn=ko- z9yV$NXU@@U_O+ij<5?W@yznP(0Y$s1bwQf#c#qe#JWx-)>d65<&l@Y2RVt&@YC zvFhF0y5>{N%ggDYT%$r?jg;1VZ#X6~HWpb!()Dp11a!Tx*tHz(5ZmGD3ja-aThCf1-LXu5!Syu>z>s$7L|1MbnONeE&m3S7xZpL&Zeg%EV9)&Z+3ipc<89< ze*LwlrX+A+0SFDF9b}*3C--@~P}=|DR3KQBw{4A;lCtcAkHqtw&4n{fj^hQ#mRRyz z{}tcK>umYvlEEhtx!ZNhB0e1m=0nBq-R#4B--rvAjBebJ2%4^;ojfEe330c$UNbkS zRk=5W3(fOmH6kLsz@3~?3e(_Vq{Zm|)mU4(b*4Xm*xY^Bh1uEV0nUOP2IC19t-z;P zgFQZ_zwh4=TdON&*wd0OkoL~hm>nbPm=x*9xBg4Z_|BOCTsX5u4&SqM=bv~fS! zZhkfyOLJ7f3A;!uH5hzZg#FNiH7UFwD(ajI>X4S66ZPs)g{pO~&(Gf<%-aOFDNq1# z=-AyVQ0Vx~m@m14fBp!u50C($o9Z-EQgSq@mZ^91l$iT24xoJ9-~W+_Vrn-xWz&Fn zg(}hvGsE^ZuI9jvX}DRIW0DWFW=I)BE~20k{P*|oEv@o2!r5{Sb6J(p-F)oyqxFkD zHx?D^v+wtDb2cYM!%e}swGS0TSJyX?_KlawZyya(KR903KtUn&zCh}Uk`N@a;b3QG zrry5USg|+;23-0RF)4@p(ZSc^a8@tk#auAIWH(pT9jO#q7WXb!8!&R45XRUlH(Lv> z$REp=7WEb$lgKazTJSJXRD`+pn<0QG4^&|rR+eF23{qst@EYy6dWXxAHD=8ruTWwy z(D3RWZo?Knj2zFbunS@hWO(KUi}*qeF_Tn4Hc<;|k z9AYt~7`k|}2}PEKU3c^6lsJc};qn&=L&x7-h*Cnky|ck6|0+>Wor5@O!Bh3y2yUYg zdN1w!^JnPu>bgUKg-Yd`#M+-hQayeL#eBRwpx43Yi1Y-l$)NWGq~yRuk|@p>Zk_Gf zlsOi^a^}4QB99<63^m>#Xc?+tV_}!9yDZ0@gTjeJ()EeC#o1ETpTxvO`IfDoU68$j z(QhYi-`M^$e0N)!hx_jU%a1%Kc!c%P#6N#VzGkw1Uv4&AAbu0bp~S<(lb6$ExEhR? zZ=XLQiC9mfB;bKae2VC&ST*IG8JhW&eeX1IZ7-&pIk_=s)M=!7Skk*Pzii!GL-s~d z8qc&J>{4Q)k(OULv*aO&)wr_V>OPb=+aMe!+N&a}dD82W+)Hr{^AWU@l4Lb3)wNY4 zgW?%g;@Tj(Wf5%IvY3H`e$P+@r7A+-NpKC|*w|F*l0@CYz#*98t{IO^cxvAy;!BN1 zrf>EzjKJzbln0&U2S3fC@IDc_s7%MAsakg<3RI?9-=8PL3-8b-+()9FdtivtXn#)c>Iq+4f$`3T&fVz{2E+N5ViWrb-Pk}sTHjfDbH{t@wvCB)k(~&6FqCDo+YW?8F$dl zDkeqv3vuk>_1ys8IsXo;nJ<8g$N%Y8x!#?V!LR{|f(;&6SsD~czPRn+6`{>Cfq6<@ z_-oO~@A31-kb4Bk0WR74@wkSu<$2Vl)M@zSF_n}KM*1HAHe`C^fXS0;_42|PmBu9C zdw``yFgY<{4VniyoE;LqJ~Ol5J+KpQ30*R!?t8B2f1iy4CnVm%m)82|Hc z-X+9x8aRd(A&yrkEe=x|e&fR+@f15iNh>aJB50W)54y<}?+wwA$qUcPgW4~!=UUPH z?Cqj*$J06uX;735Jk zx{%lA$a4wczhp!T;J`*Q|e5nZimozK6n)i#A&!ZtHrf#w<-=&q>ou#%8*DLR(Jy+(S zsKQrvH0%|X6}E=@%z4%Mavfv5spjtH_E*n_z`cH4T#xSkN=!eIAH_I)NIix%C@&vu zhI9`%Y#GrbMzhf~VOKV_4F(39)ipIqXWz4U!o~)1V|;)^e+Q-*4U!Agr7d@xGlp|= zPL8n;Lp%&4_$&tYse=i%oqRtVpV;TsK;u%Al%}opfq!RgpVrmhPjUp@T-;o2`)7TT zGxNuP)E>i_9VrWpBZM+0Vopj zgEx(o_g>iNBNjtZsX&hDB4@L}plj@WW@ZUmPc7tDsS zjS5o3j7Lbjjm^CZBxs0#cZ8cs3KDVM2$m}h{3ASDnL9F<&Sr+Gq{4puo#tOh_|&39 zy1oZhrVSH9)1CS`;fNYBG`lbhBlW1|KV(Br&1#jX`c;3N<@V(;^+d#d_Rzh{x>FWD zY&s46qh^~uHM6+5B)eh9Ri?yo(t|W-GTLu6sAF4I)o|@f=n+kUyNA=mhlvb(fgHuN za@eG!@S~x$e0aQm`^Y0d2cP#BKNIdcrV%wHy5J!FdqCdO)l+GgVea^aQ`rDgK{<^O zUEduN{jB@a;uTMz1t_qUyoF=1GOOOWd_J$qF)x0;F8BBzE-o9gb8&Je&T%I(iMw(F zP!;->-Lp2R*1HE;X>ic!H7l>rS6|;7EM`7tzW2;~6wRL~a)FFus0=!r6TJl zK!$VkBkew9$Yu_&ArfN_CA1D5OcO6!O=xaNJyNcd0nV>3Ke|-4F= zVg7p7tKd`86x?pgsu^U)C!|%XJFkb1&&q}Otsz!S(Hf`|2qTs65AY1x4nEN^ZLJIs z5|3c+{u$vIX4-C4_hlvt>^s|73U@I8?3!+ z7SRc?jqSvK*JjdL=$@0%%HX!eoBuGCBN^qOrPepnRsw3x1rA5o%@ z!RP5G$In(8mV9xuay;OGWTlq=jv_0KRv5lHY@4&xlmdTL%j0&o4ia;}lG!-6Z4=4a zQcf)rBL_uL3QbB@NNN0K?r#8`bCzb}()1XK208Na!HW zKs_N_%4=J0m(Mn;KG<{yyUXbU?baU&#Bv17X`70gn%uB#7+NKVJ~>F?GJqM4FKk0N$sx%9k>6yU-Sdcy&U8s#-{_tVFWA?LWrov1(LAv9R z6W6TS)TAXo_CDXGXiWti-y9Y}jiJQ9r)u(D+4i=6udo_VE@Sopp@^M2Rtf+n=>vn& z%~QRu7-cWe1@At?T6c&f+h+MyBG6KwW5T~-+y5Z*T?;6p-jJoYl|o?~)gf_5K=H15 zZO?W)9&@I{#13)NC#rs?r?Nd|zi@3hi@>C0&(D%X*3Oolp0aBhxhUv)S@M;kNjm0D zdv4+$RFYxVGco{Qe%QGlVuYa(+d+&M_8PN5>FQ=?`aKO|jG!c^$h_FM+8b|jBGafP zmNE6h<>qig5xx5P)vyx2O=2LpN7WrIwiyty(>&2v*G9N?GlP}~ zEhjGEV;$9OE#TpXdQ*z?mpgv<^V=Yt0QzwH6)P&L*pv#E`ng5lk9!ES2I1DV7|-mW z#3HA>`}!dgt1d_c9)p-up7nveNkO2 z*Pb`Ktj}0k;V>QYG*m&B#av%URrPkga(9UNV&&!siZT@;pW9_)*XuaFmkPleAVK=# z!BeJ+8+5V=6EwJ_`$f|-gwp%Yj0Pb!N(ZFj4F7o`hhYtIJFlm(2-TIMTp&f~*md{f zI;>y?V((QL%Y<-T6toaIcuFE<8x40QIq~WC$O(%?JL}QlM5%*DzXY>_6SlU8y+ zkn%3L)@<)Yle@9Ul;%9V@x%!+hf&+-f`0ky*>b}koQE0WJVnb8zNMw*sS`v!l%S)d z7iv~;q^MWGju!^VS5~Q5rx>_10vk{f6OhmzV(kPZTw_folV3w zbTn!FFwKdJYuk!{j&#}NwxE^-lK)+dr0zC;b}hguB}6qs8~G9?h$C>olY5tF?)#@z*(nCibCOD53ts}mX2l9W6wk%@Ty^1j~s zw7rV+y(iZ-e;~^PWuMR2Vkj=aU%z-Wvonc~o6_0)^OX^lnLMR&fzi>?0~MOpE2@Tu zzGK{Tcgvf{6LZu#u2~(Feg1KijL~G1C=@(KbScKtY~aqGjFBviyd;YDrX%BCAEHO+ zaID66alH zL^!i(LCse9ZvAdQ7#`f3iS%}uw?K;<`-%r&^orzv((^V|3{U#2MkADmE4R|3d zL(0+4;{isuiW%~*#;^A$YsBw2abGtZSH5Yn)g9p=I^-(N?rVEPs?x`&D9QY<>o`>J zOaU=ptYVC$m-%YqLCu!yS{1R~zs50?G?GQHmh$GWC$lGa+te>WbZYnznRcx?=VXo$ zhPfkc>p2t6+5=DH0tduch% zN1rRpzknGCnpYz9epsbes2V2yh=R$#F7C_yEtL1fguuKb8iA<%J$uZpEn@YcG>b! zK&$g|xX19JMySV_$7oKU1r!&q`(WAKF8@6|OvlC&w{2W9bdKug0hueytgLDjCbDi? zW`w@XRi~n4UT(eL*0z=igbW>``c}Ho#FCs|?9+KolZZ=H%gz&|&95-07~bEP6ta-> z5N$){fYWAcST!HFJ6;By6Jj*|!LM$G_rQcR zCK_++qfsT-56nK%Ny3>G_D`gA%5(3tQMS@BK4}uwupnGm{w~S_I2A&o=Pgi_{j@%5kMYytgYS<` z(4RFL4MQe$^lo;$8bc9$uhl714IxytMEFFaNXwBF%Ni*`S zgP~CiEib3r0`<%)EvRd0IjLHuEuS&M!36D}X~HCrg&Hv>ae>6oRT)+p%tEiDdo_Yj z=SeA`DBg*Rk*dU-<9YMYd${%0T-;GihkD&ABl4TgU5-X&NBk*jk~AZ4S;Wy3q1F_e zz{mA^XO9In(b+S|_|X9seL|$bJiv^s_%+7)H_URr5mYqajqmq-OqbZ5H5Qi3vF3sq z9NO+-$DZ9r>xFe@u<#?_A-!Qlm00P{I6=ev7t&J>^yP_y;7~daAU_F&7-T5AfTF)4 zY_P4biSyoi3Zn7SZX1cza#FNCzi%tT^aAHV@A35~um`I%s!B6=wb>T`<4U*5i8-8hsHX90+G#@T(TwK`RsenyFk9&ko z8t182oMAH?ws#d3*sj(8Ro%0$={n5I9jf!NGm99%&@?(~23#V+yr=Dnv7yH%k5kmT zuj;2axPv`XNNLP03gUknLPe&%afBAE{O`8Z&I*F8cLf#5ha~YQhSUT z+{MU@25QYGI=OkD4J~__B(jx3X;b*Ut?8Y7-Bjdm{pQR{dwu_W$v2MQ51T98z1iEQ zNMwpmAl7g4UWCQPExYP^-i-p!)Bl@C-h8}jncFpWaX0nk$?r5*t_As_pH2V1g2rvG zs*|D5RPp-yjqBZM?;BULk;|e6Q=T`i;pYycR`asD%{^b$7MbG8_FlswP9M-iB2R7> zjNUZApzIsnV_HyM0e+w_rYSG(<~2_W0h?1|9tAtnm?O%lJCc=2oPfHk=^v~U*od|* z9mgKBV1>#H$yTE}f`;&m&}L|Vce_;(G$yVGaNXZC3nL0c9P4v^3!*!|PyywQw2j$p z;8#v&%%S}i%TZ}*A&o$JOhYG=K~)yrC7Nv7WMC!GIo}+bR!zlY zo4av|BWV5*Oj2>3B_=+vM)-+>OA0bXhG}-frx#|!ti#9#IAYc=3`ULt!le+~Re~2- zq-b@$zv&I9JN}#nk81faRwJM88*vz$*4*_0U>cvQ2;W(8G%mLGnlwXPNrctUz>w;} zVbW2W&x~S~|Fc#xPO7H}Rm1?&)C9yXh4YrvbYtp%=#@z{Y_^`g*yi?0^cG?p2Z8#z zqTfIYz}t64^zwH$P!lo)wZFwBOtIi%j`~;#b%NsUvg@omN$6!v z=_jj(to}7@?E8k>*3|29fdG3_BKmTZTeH#0jeGs^(J#|HxNGCz<_o0@K2|3uDaD5K zvFnwUOwR4o{GZQz*m$P=Z=Ii`O7(ikzV00}7GG4K?&N?fWn&tlNdvZb?5y5o>VAw(RR5@kvXTp7>^nkht0Ze^EQvXZ;kN>Fn1RfpCv%jRf;G8Gz?f8|MStu5`sD+nitr6C z1T0$C9o61IeIb0X$~1fXn_foS=Z{@u92^gA=o!zEOQ}m0j7!~>axYFCM8W2s5reww z>YYYZ374!{F-;X(HJ1}(V<*E`e2H5nOrX0*Kz;-Fzv;W51wDd`&s$u-!>7jBZ;Zz z%6F|vyor(&QJ?Q_0zYZUhSPYgSt>^ImeB+Xx4JwOob3+27)t9L;e3jZd zu~kb|DA1vGLQhi14>TwxhDOxshAztw4~rKOv9()l*IZ?=Z3}^f(j}qQW#_#Ckdc#< zll{%H)fGy)Ww|)lZ%1JRJB7w9qxo54f?8>+)7o$~h#7f;6o=eyG=R!|3UoJLLtnGG z$v<6KBeB_|lMHn=1|2H_TXG_KK&_mAph+T1ldZ)?x1&#DeZ8{YI8G~75i)^-v`f5Q zG$=o2u4cZG+ojh{z`2ZA=T)>pcG@91$pDPMe}I7J3`}QF=*jF{h?85vc&O}W$tSVS z^@`Rr5Q>1+MRfN$dWWJBO1vZ92Uqu$f^k(aq($&#y)a9TP|CuL9a)CQo0RvMj_=7w zhJ*61*C!~RtoEj3u7PK1Jf!a%v7PhD4nvcS&i?ry}ycv{a zJ@|AkHeJ^$sF~XPEO3gzqJ}`^aMJtg=ZCfH<+=whHTKc2SVN~^E++s^n&~z^5@e%W z6P%v6#S4F)G)nr#*`6@_LGNyLk296cY0Nt)QSVC7+?58G$l$ z@5$e;%*~MbXGd13n<-bF&Se`VN3mwhC_58q(`x#VIlfq-MfAS;)V&OzEHkw9^}KW2 zt|YXMi43J#fJz?_5Kn<-Dnsk3-RjI)XiTL!iTbWqS zpS7UXrw$r`7*LC#Z%66uMkyj!g~NNw7l7gp&JVb}a1vd?g-Ot6fUCiEiZcFJiQ6l~ zy>s=~jHNH39>bU|^G%BTaZe&_a?COD>Bz|GF4xZeJ|fDsdV!X_7v?|EWNBBIfZ0}G zkjLB8#l+sgj(C$~!}x{k(Z9;21!bD#@GM$mM^Rr}{35mtsggxk2Vh~{^12rZHT!a> z_d{gr-_-{E%bqV^UYl%35%--C9PXsCgqyMMxZ)IIorryvwxOaYcq3!QyAUb>G@D5Y1TmI4IjmjAs8LA1d1OgefSTr_iZ;9q4X&Az~XoEoDw+QQJmD+^`%#X@A#i(Ucn>Hyr2n zes@;|fy1(nrn}A|vKq&rEsL=$l_6|CmiS*DfLRQP zWZDFD_UamjM#RZns?=Tl7$uL>S7)^yFM|ABQSteFnOjg2{Nk>9xwop)Em5PUq)OdA zqTTw@V4*j8sNP2jIU0f(b*)40w*R~*SuvlXPN%`_`>1PxJYp3zw~~>aWJYh$I?Gnm zx}vJB{qxV|?a)|+mXXG#$DZ4eiKJ&oRmmA0CR9k!Oaebyj3zV>bOuXQGWs7zHXf7W&6bs~jXZ(6Dp3(!_C$Jwt zYg35s9wsT#d3x%PzrOB`kE@j={|FLEOh_t_QIOAx_}%Fp%~is?F%1u~(wdF1o7A$8`W!o+)hNBMg3+pmI_nOSRjX^Ac?Gjrdx4LI=hgp?tgfQ|$+f4yuI zIb|o;q&-Qy-yi|?ulG{CRDt`1SjbY0JZE3E3}cDxw`9ua>WKyUn!k&cQcC6Y&W7(EMRs7BfRuia&4|PNpWC!)h8O`T5n*o(evw zNJvU0gY%0eGrG4pzvCRv-ot$7>wZjS(kA@&kb$qQ5!KPjST|>*yuZJvv?rJ`4G;Vl zHn6J<7le(3LB$mkhzJcK&n+OZmYGh|QmI`R7|KYK>|lSs!YW~DS<+rJQ*e7jBrzKk z7!4l@Qr^*{N4O`@Ov2uZnFX`r9<+VGSEf}VZRdzHIY>vT)cV^+bd(Ye>Epe|JH?i53Ot-{B}2ZPq(cS z9v}_HFd{PE$S|6bgRmOmtNg6%kJzDH8mycJWwM@Riy^rHh)Qywktez5K79m{wK$&9 zzb0@-$oaxa0Ef!o$NC7zL#q|PH7;l7!48CgGlyD=i5R~hyRMD`V@Qo1ycEg66%t_( zB1^!ra& z2w}5W{kZolA@cen)`Erzp#M;OTdrFM`I6^QoR$<)_TB%{&kwHtM^l_wy2L(XZWXBC3% zZAR!keaIr75+))jHW4RE9nm4I9o;?^_^-V!=jB(xQP3Cjo!cvS~KB96= z{#poA+Kki>k+527hJCj(mtWEo)MOm6Y`68n`knSP(Id5DT2d(Afp#I)k2xm!!=Iu4 zG7MTvr7jU)S*mP%A6M^}S89&ih*-v;8x_sC1+l?dskk!>-i!d`P1JjCRt6q#DCV&I z+Qv!D(W#kWXMHM)Um^_Hh+{7T*#fg0|DXwvm$YZG5T8E^SD;zgs*QrjSmh&jA*zVt z%QWKS^TP_E(2iY>>&pPjdkVuZ0S|fs@bL>p;Pb9z`6I{XuiS4jqaT@hZh6M;>pd3~UUh`h}`4hVnZ}Ph{Dtq4;cD}eH(K^Qa=MPN=+DJ=@ zWX1MJ>FbeozP{RsKDo*K1H`D23XfxHDZmhLSsZ!n-IKV&$*L&fA5>sUD5oW}_M}+MSM;xKaI74y8!R`_sO*IR+HQB}a(5ZF;6d8$Te`kT zvWn$xD7h9wqZ*WVnsRSD{dN{{fN0;o3*?pf&cQGz>;QlUGnCO^pE8KSx!p0USVZ*~ zS?Tv*s5=~_F9rezRHao`{+mSX+EvIR(GsMX>Kar*tuHFS#n)s2Ztny)1WtexcU!U7Nfq;_DJBI0uQ-{p1dVpG>Z~PI zzF0B@Zx?2=EKwmDaV;rqyBxA{;Gl&g1U{7obHCZ4?@(4x0`*tjU^b{=Ul2~82V++K z(?JQ_k_9dohZ0>y#p0IP7gR$U92gm1jOx(T4{-eU0@XrqGq8Mw0DqWG!mA=CbHFwV zOojJgFA+m%4`o9dlD&RNL}fzLAq2EnaqE&(EMZWy5+F;(AfV!T>Hkr8#%9p|s9as} zF`teuy5vZcRx$hE`naHWJ3l4$S+qA;R{;sWby_PFPnb>487^Bu;5gW*%Yi`C z#&Us18hokkrN-yX*%Z(=0-=c1lpy;iUJ4)n{JGA`({83pHahqW2xXG6`LgXzM9-fu z?!6mbkd3dvA{nwT)+dDyk%e;9fukUZ>yMYF+arw{-4eCl zzwPp(Ow!)BXCE+fD4u_SUThAL=p`X(pNQYC^Gt%!Lvrn#tIQNAk2nbXx|d|$Nak>- z&ijqmBZ8(KfrNw409C)AL%2`kSH-F=^0CcXXuH}sK)Z9?fo z&&NsHR;V26f1knK5=PJHuV?S41CzL(g|k{aq_DtKchP8hhvbA5gtC*d`1DH1Z;`AV zkyHuN6ye`$Mi7T%?M%?^vxZ`KN4_y(QWB-%1Rg`cx5Go@+5?)!S%;;Ej-?auqwo+U zFemP}!dc8ijxBZ!-cUjnAH%=_FXJ3;C7Q51Hzf8BYF8EdD&DrWlE{r z4D7Uk5Mcc2;-+;;Nn;fh<-r#^?6QyRulEy-_7VRV253fMXKWQKwjTPt?=v)8Up<#$ z_^VaJ=?qxm;5o*z*z#NHGpyM#vg;NaDU|nK^8n;Yl3ps&t>?(jgWkps|MF@^kT@Hl z&wY^lDEGv6m~R`xBZk<-Agt2?1GSXw>IkN#Xdh3o3REIC-`26jmwIF3Pz`skmElxY zQh`J>q(jT1l8mQ`4|z(8=$9DzMZz}{PypOMZg+jQ$htM-z{_gGV|G30<%uBDRY04; z#~axEh>XRz%;fvHcg3SkV9M8D_lX+cEzh#$tpbQ>P++4;1|M~HZHBy}Xj{`w(uvsR zm6IB1&zniZ)zJ{j6k#nE@B7n-YM^M?zMW{LJjjBUq6qm(^6Uf1ynhKn^GEK$@a&jn ztzQk1DG>lrITxrMJ|%jWDfbwoD}s^V_58Vt8?B0LMT0V-hA2yh#D%vu)jI&3s{aW} zOHL(&W7@rRI36F{cO(rEL?^2c-~MHNB0gs!b~HiT8EWtD{Eaek^pVp1;KHJ4{f*7X z?(OOGS`|eZsuZk18MNI}BC!3sU9}{RugxV=N}?#NJ!Gzo>@2`o*nWEbINl?h z$^PG~ScahLBk97GaR>~Mp+3$Sn1D(ZDc~qCNr6uHNk12(R=OZ6h)e4$8=L|qmh+J> zCkba+Us%ep*2A0;#wv_{9V8+`0P5di$zYgWwuZ!M9=Jj=25>A8pYHF$F^4+rux8<+ zIk8y`pBD^g{^P<e;x*++gz`wOWmg!L9Tu7v zg_|7U1VCm=4+Rp5Rrm>Dxm*kOO|5 zKpD#EBWU!+i@>n^(?dYeKEDH7;A@xrCx!!hhiHY+{!@D_J;&HZ$eCSv_oI}MHS~CE z-v52U%zYWzd_~j~Pleg5J$!oow6cLBSGsYFs;EfMKl->0>fCEZY1A0hQ>jhF*ys{k z%_jY?O@m(zKjcUOqhW7O*DtD9dV zFIj=K+HXzGP(BVv94P$TkmJGsy?hOv%%>60Qu(`DMYDhoqbqYB%A|K|Y47`1MWpGK*O2i!J`Lmnt=6u0O zjSaA_kZmuIO%4^!=f~t|2(YBcw^xq*#0oR0127R32K%L3=m>>!e&j2+>QfxHCn8!d z7h}&E+Hq>lCJ)Uf8(NwKV~7_+URoe^`R4Z(`|5y8zW zbEp+6Mk+xAP!5Igg%0jF_b1QL{VCdJfd-|*i5ucY#>uctVOOVpx-Su(1|Jj^mY4Me zOW(f}FW_>xzO?WMx(YW+PA|2(YYZvb3Hkpns85plbeYnWmAUw6Six)j{pVz;X3W$| zwSz1ELcYJ!q>Kf+ViBE%PF(AppRepositoriesImpl(remoteDataSource: Get.find())); + // Get.lazyPut(() => SendPaymentController()); + // Get.lazyPut(() => FeedBackController()); + // Get.lazyPut(() => TransactionHistoryController()); + // Get.lazyPut(() => ForgetPasswordController()); + // Get.lazyPut(() => BeneficiaryDetailsController()); + // Get.lazyPut(() => FingerPrintController()); + // Get.lazyPut(() => ChangePasswordController()); + // Get.lazyPut(() => LoginController()); + // Get.lazyPut(() => TermAndConditionsController()); + // Get.lazyPut(() => ProfileSettingsController()); + // Get.lazyPut(() => SendPaymentController()); + // Get.lazyPut(() => LoanTransactionHistoryController()); + // Get.lazyPut(() => LocaleController()); + } +} diff --git a/lib/app/core/config/api_utils.dart b/lib/app/core/config/api_utils.dart new file mode 100644 index 0000000..6c542f5 --- /dev/null +++ b/lib/app/core/config/api_utils.dart @@ -0,0 +1,60 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../constants/translation_keys.dart'; + + + +class ApiUtils { + static bool isHeaderRequired = false; + + static ServerResponse parseServerResponse(Response response) { + return ServerResponse(response.data.toString().isEmpty ? {} : response.data, false, "", "", response.statusCode!); + } + // static void parseError(ServerResponse responseModel, Response response) { + // Map errorResponse = response.data; + // String errCode = errorResponse.containsKey("errorCode") ? errorResponse["errorCode"] : ""; + // dynamic arguments = errorResponse.containsKey("arguments") ? errorResponse["arguments"] : []; + // responseModel.setErrorMsg(replaceArguments(arguments, TranslationKeys.makeTranslation(errCode))); + // responseModel.setErrorCode(errCode); + // responseModel.setResponse(response.data); + // } + static void parseError(ServerResponse responseModel, Response response) { + dynamic data = response.data; + Map errorResponse = {}; + if (data is Map) { + errorResponse = data; + } + else if (data is String) { + responseModel.setErrorMsg(data); + responseModel.setErrorCode(""); + responseModel.setResponse(data); + return; + } + else { + responseModel.setErrorMsg("Something went wrong"); + responseModel.setErrorCode(""); + responseModel.setResponse(data); + return; + } + String errCode = errorResponse.containsKey("errorCode") ? errorResponse["errorCode"] ?? "" : ""; + dynamic arguments = errorResponse.containsKey("arguments") ? errorResponse["arguments"] ?? [] : []; + responseModel.setErrorMsg(replaceArguments(arguments, TranslationKeys.makeTranslation(errCode),),); + responseModel.setErrorCode(errCode); + responseModel.setResponse(data); + } + + + static String replaceArguments(List? argumentsArray, String errorString) { + if (argumentsArray == null){ + return errorString; + } + for (int i = 0; i < argumentsArray.length; i++) { + int indexToReplace = i + 1; + String valueToReplace = "\\{\\{*value$indexToReplace\\}\\}"; + String replacement = (argumentsArray[i] ?? "").toString(); + errorString = errorString.replaceAll(RegExp(valueToReplace), replacement); + } + return errorString; + } +} diff --git a/lib/app/core/config/connectivity_service.dart b/lib/app/core/config/connectivity_service.dart new file mode 100644 index 0000000..e46f385 --- /dev/null +++ b/lib/app/core/config/connectivity_service.dart @@ -0,0 +1,46 @@ +import 'dart:async'; + +import 'package:connectivity_plus/connectivity_plus.dart'; + +import '../utils/logs_utils.dart'; + +class ConnectivityHelper { + final Connectivity _connectivity = Connectivity(); + + late StreamSubscription> _subscription; + + static bool isNetworkConnected = false; + + checkNetworkConnectivity() async { + initConnectivity(); + _subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + } + + disposeConnectivity() { + _subscription.cancel(); + } + + Future initConnectivity() async { + List result; + try { + result = await _connectivity.checkConnectivity(); + } catch (e) { + result = [ConnectivityResult.none]; + } + _updateConnectionStatus(result); + } + + void _updateConnectionStatus(List result) { + dp("Connectivity result is", result); + result.forEach( + (e) { + if (e == ConnectivityResult.none || e == ConnectivityResult.bluetooth || e == ConnectivityResult.other) { + isNetworkConnected = false; + } else { + isNetworkConnected = true; + } + }, + ); + } + +} diff --git a/lib/app/core/config/dio_exceptions.dart b/lib/app/core/config/dio_exceptions.dart new file mode 100644 index 0000000..181b91b --- /dev/null +++ b/lib/app/core/config/dio_exceptions.dart @@ -0,0 +1,93 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; + + +class DioExceptions { + static String errorMsg = ""; + static int statusCode = -1; + + static ServerResponse responseModel = + ServerResponse({}, true, "", errorMsg, statusCode); + + static ServerResponse parseError(DioError dioError) { + // + + dp("============================================", dioError); + + pe("Error response", dioError.response); + statusCode = dioError.response?.statusCode ?? -1; + responseModel.setStatusCode(statusCode); + switch (dioError.type) { + case DioErrorType.cancel: + errorMsg = "Request to API server was cancelled"; + break; + case DioErrorType.connectTimeout: + errorMsg = "Connection timeout with API server"; + break; + case DioErrorType.receiveTimeout: + errorMsg = "Receive timeout in connection with API server"; + break; + case DioErrorType.response: + _handleError(dioError.response); + break; + case DioErrorType.sendTimeout: + errorMsg = "Send timeout in connection with API server"; + break; + case DioErrorType.other: + if (dioError.message.contains("SocketException")) { + errorMsg = 'No Internet'; + break; + } + errorMsg = "Unexpected error occurred"; + break; + default: + errorMsg = "Something went wrong"; + break; + } + + return responseModel; + } + + static void _handleError(dynamic error) { + switch (statusCode) { + case 400: + { + ApiUtils.parseError(responseModel, error); + } + break; + case 401: + { + responseModel.setErrorMsg("Unauthorized"); + } + break; + case 403: + { + responseModel.setErrorMsg("Forbidden"); + } + break; + case 404: + { + responseModel.setResponse(error['message']); + } + break; + case 500: + { + responseModel.setErrorMsg("Something went wrong, please try again"); + } + break; + case 502: + { + responseModel.setErrorMsg("Bad gateway"); + } + break; + default: + { + responseModel + .setErrorMsg("Oops something went wrong, please try again"); + } + } + } +} diff --git a/lib/app/core/config/error_message_model.dart b/lib/app/core/config/error_message_model.dart new file mode 100644 index 0000000..833a5e6 --- /dev/null +++ b/lib/app/core/config/error_message_model.dart @@ -0,0 +1,41 @@ +// To parse this JSON data, do +// +// final errorMessageModel = errorMessageModelFromJson(jsonString); + +import 'dart:convert'; + +ErrorMessageModel errorMessageModelFromJson(String str) => ErrorMessageModel.fromJson(json.decode(str)); + +String errorMessageModelToJson(ErrorMessageModel data) => json.encode(data.toJson()); + +class ErrorMessageModel { + final DateTime? timestamp; + final String? debugMessage; + final dynamic trackingId; + final String? errorCode; + final List? arguments; + + ErrorMessageModel({ + this.timestamp, + this.debugMessage, + this.trackingId, + this.errorCode, + this.arguments, + }); + + factory ErrorMessageModel.fromJson(Map json) => ErrorMessageModel( + timestamp: json["timestamp"] == null ? null : DateTime.parse(json["timestamp"]), + debugMessage: json["debugMessage"], + trackingId: json["trackingId"], + errorCode: json["errorCode"], + arguments: json["arguments"] == null ? [] : List.from(json["arguments"]!.map((x) => x)), + ); + + Map toJson() => { + "timestamp": timestamp?.toIso8601String(), + "debugMessage": debugMessage, + "trackingId": trackingId, + "errorCode": errorCode, + "arguments": arguments == null ? [] : List.from(arguments!.map((x) => x)), + }; +} diff --git a/lib/app/core/config/logging.dart b/lib/app/core/config/logging.dart new file mode 100644 index 0000000..e4b7fb3 --- /dev/null +++ b/lib/app/core/config/logging.dart @@ -0,0 +1,52 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/requset_attr.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import '../dialogs/custom_loading.dart'; +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; + +class Logging extends Interceptor { + late RequestAttr requestAttr; + + Logging(this.requestAttr); + + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) { + showLoader(); + + // refresh token if expired + if (ApiUtils.isHeaderRequired) { + // options.headers['Authorization'] = 'Bearer $API_KEY'; + } + + print( + "request_data =>> TYPE: ${options.method}\n" + requestAttr.toString()); + + return super.onRequest(options, handler); + } + + @override + void onResponse(Response response, ResponseInterceptorHandler handler) { + hideLoader(); + print("Response_SUCCESS =>> ${response.data.toString()}"); + return super.onResponse(response, handler); + } + + @override + void onError(DioError err, ErrorInterceptorHandler handler) { + hideLoader(); + dp("============Error Response", err.response); + ServerResponse response = ServerResponse.init(); + + ApiUtils.parseError(response, err.response!); + + pe("Response_ERROR =>> ", response.toString()); + + if (err.response != null) { + ServerResponse response = ServerResponse.init(); + ApiUtils.parseError(response, err.response!); + pe("Response_ERROR =>> ", response.toString()); + } + return super.onError(err, handler); + } +} diff --git a/lib/app/core/config/requset_attr.dart b/lib/app/core/config/requset_attr.dart new file mode 100644 index 0000000..9b88b4b --- /dev/null +++ b/lib/app/core/config/requset_attr.dart @@ -0,0 +1,40 @@ +import '../enums/http_methods.dart'; + +class RequestAttr { + String _url; + bool _isDialogRequired = true; + Map _headers = {}; + Map _queryParams = {}; + Map _pathParams = {}; + Map _body = {}; + HttpMethod _requestType; + + RequestAttr.withParamsAndBody(this._url, this._requestType, this._body, + [this._headers = const {}, + this._queryParams = const {}, + this._pathParams = const {}]); + + RequestAttr.withHeaderAndParams(this._url, this._requestType, + [this._headers = const {}, + this._queryParams = const {}, + this._pathParams = const {}]); + + @override + String toString() { + return 'RequestAttr{_url: $_url, _isDialogRequired: $_isDialogRequired, _headers: $_headers, _queryParams: $_queryParams, _pathParams: $_pathParams, _body: $_body, _requestType: $_requestType}'; + } + + HttpMethod get requestType => _requestType; + + Map get body => _body; + + Map get pathParams => _pathParams; + + Map get queryParams => _queryParams; + + Map get headers => _headers; + + bool get isDialogRequired => _isDialogRequired; + + String get url => _url; +} diff --git a/lib/app/core/config/server_request.dart b/lib/app/core/config/server_request.dart new file mode 100644 index 0000000..94064db --- /dev/null +++ b/lib/app/core/config/server_request.dart @@ -0,0 +1,121 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:dio/adapter.dart'; +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/requset_attr.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../constants/translation_keys.dart'; +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; +import 'connectivity_service.dart'; +import 'dio_exceptions.dart'; +import 'logging.dart'; + +class ServerRequest { + static Future request(RequestAttr requestAttr) async { + /// Internet Connectivity Check + if (!ConnectivityHelper.isNetworkConnected) { + ServerResponse serverResponse = ServerResponse.init(); + serverResponse.isError = true; + serverResponse.errorCode = "ERR_CONNECTION"; + serverResponse.errorMsg = TranslationKeys.makeTranslation(TranslationKeys.ERR_CONNECTION); + return serverResponse; + } + + _initRequest(requestAttr); + + try { + dp("============request Before>>>> ", requestAttr.toString()); + + final response = await _requestDio.request( + requestAttr.url, + options: Options( + method: requestAttr.requestType.name, + headers: requestAttr.headers, + ), + queryParameters: requestAttr.queryParams, + data: requestAttr.body, + ); + + dp("============after Before>>>> ", response.toString()); + + return ApiUtils.parseServerResponse(response); + } on DioError catch (e) { + ServerResponse response = DioExceptions.parseError(e); + // if (response.statusCode == 401) { + // return refreshToken(requestAttr); + // } + pe("============catch Before>>>> ", e.toString()); + pe("Error responce", e.response); + return DioExceptions.parseError(e); + } + } + + static late Dio _requestDio; + static late BaseOptions _baseOptions; + + static void _initRequest(RequestAttr attr) { + _baseOptions = BaseOptions(baseUrl: attr.url, connectTimeout: 15000, receiveTimeout: 9000); + _baseOptions.contentType = Headers.jsonContentType; + + if (attr.headers.isNotEmpty) { + _baseOptions.headers.addAll(attr.headers); + } + + if (attr.queryParams.isNotEmpty) { + _baseOptions.queryParameters.addAll(attr.queryParams); + } + + _requestDio = Dio(_baseOptions); + _requestDio.interceptors.add(Logging(attr)); + _requestDio.interceptors.add(InterceptorsWrapper( + onResponse: (Response response, ResponseInterceptorHandler handler) { + // Create a new response object without headers + final newResponse = Response( + requestOptions: response.requestOptions, + data: response.data, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + ); + return handler.resolve(newResponse); + }, + )); + _requestDio.transformer = DefaultTransformer(); + + (_requestDio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { + client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; + return client; + }; + } + +// static Future refreshToken(RequestAttr requestAttr) async { +// RefreshTokenRequestModel userInfo = RefreshTokenRequestModel( +// porOrgacode: SessionCache.instance.userInfo.porOrgacode, +// pctCstycode: SessionCache.instance.userInfo.pctCstycode, +// cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, +// cmpUserId: SessionCache.instance.userInfo.cmpUserId, +// token: SessionCache.instance.userInfo.jwtToken, +// ); +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// // headers["Devicename"] = "Mobile"; +// +// ServerResponse refreshTokenResponse = await ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.REFRESH_TOKEN, HttpMethod.POST, userInfo.toMap(), headers, {})); +// String token = refreshTokenResponse.response["token"] ?? ""; +// if (token.isEmpty) { +// Toasty.error("Session timeout, Signing out..."); +// Get.offAllNamed(Routes.LOGIN); +// return ServerResponse.init(); +// } +// +// SessionCache.instance.userInfo.jwtToken = token; +// if (requestAttr.headers.containsKey("Authorization")) { +// requestAttr.headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// } +// return await ServerRequest.request(requestAttr); +// } +} diff --git a/lib/app/core/config/server_response.dart b/lib/app/core/config/server_response.dart new file mode 100644 index 0000000..eb37a76 --- /dev/null +++ b/lib/app/core/config/server_response.dart @@ -0,0 +1,72 @@ +class ServerResponse { + dynamic response = {}; + bool isError = false; + String errorCode = ""; + String errorMsg = ""; + int statusCode = -1; + + ServerResponse(this.response, this.isError, this.errorCode, this.errorMsg, this.statusCode); + + ServerResponse.init() { + response = {}; + isError = false; + errorCode = ""; + errorMsg = ""; + statusCode; + } + + Map toMap() { + return { + 'response': response, + 'isError': isError, + 'errorCode': errorCode, + 'errorMsg': errorMsg, + 'statusCode': statusCode, + }; + } + + factory ServerResponse.fromMap(Map map) { + return ServerResponse( + map['response'] as Map, + map['isError'] as bool, + map['errorCode'] ?? "", + map['errorMsg'] ?? "", + map['statusCode'] as int, + ); + } + + ServerResponse setStatusCode(int value) { + statusCode = value; + return this; + } + + ServerResponse setErrorMsg(String value) { + errorMsg = value; + return this; + } + + ServerResponse setErrorCode(String value) { + errorCode = value; + return this; + } + + ServerResponse setIsError(bool value) { + isError = value; + return this; + } + + // ServerResponse setResponse(Map value) { + // response = value; + // return this; + // } + ServerResponse setResponse(dynamic value) { + response = value; + return this; + } + + + @override + String toString() { + return 'ServerResponse{response: $response, isError: $isError, errorCode: $errorCode, errorMsg: $errorMsg, statusCode: $statusCode}'; + } +} diff --git a/lib/app/core/constants/PinType.dart b/lib/app/core/constants/PinType.dart new file mode 100644 index 0000000..da2902c --- /dev/null +++ b/lib/app/core/constants/PinType.dart @@ -0,0 +1,4 @@ +class PinType { + static String PIN_TYPE_SIGNUP = "01"; + static String PIN_TYPE_LOGIN = "02"; +} diff --git a/lib/app/core/constants/api_keys.dart b/lib/app/core/constants/api_keys.dart new file mode 100644 index 0000000..d1f0048 --- /dev/null +++ b/lib/app/core/constants/api_keys.dart @@ -0,0 +1,141 @@ +class ApiKeys { + + static const String cmpUserId = 'cmpUserId'; + static const String cmpCustpassword = 'cmpCustpassword'; + static const String channelCode = 'channelCode'; + static const String porOrgacode = 'porOrgacode'; + // static const String pctCstycode = 'pctCstycode'; + // static const String cmpIdennumber = 'cmpIdennumber'; + // static const String cmpUserIdType = 'cmpUserIdType'; + // static const String arguments = 'arguments'; + // static const String cmpAccountno = 'cmpAccountno'; + // static const String cmpCustcode = 'cmpCustcode'; + // static const String phoneNo = 'phoneNo'; + // static const String obpPincode = 'obpPincode'; + // static const String newCustpassword = 'newCustpassword'; + // static const String createdDate = 'sgtGntrCreatedAt'; + // static const String narration = 'sgtGntrNarration'; + // static const String deposit = 'deposit'; + // static const String withdrawl = 'withdrawl'; + // static const String balance = 'sgtGntramt'; + // static const String transcationDesc = 'ptrTrandesc'; + // static const String generateDate = 'sgtGntrdate'; + // static const String valueDate = 'sgtGntrvaluedate'; + // static const String amount = 'sgtGntramt'; + // static const String chargesDes = 'pchChrgdesc'; + // static const String porOrgaCodeDbName = 'POR_ORGACODE'; + // static const String porOrgaCodeVarName = 'porOrgacode'; + // static const String plcLocacodeDbName = 'PLC_LOCACODE'; + // static const String plcLocacodeVarNam = 'plcLocacode'; + // static const String requestIdDbName = 'REQUEST_ID'; + // static const String requestIdVarName = 'requestId'; + // static const String userIdDbName = 'USER_ID'; + // static const String userIdVarName = 'USER_ID'; + // static const String channelCodeDbName = 'CHANNEL_CODE'; + // static const String channelCodeVarNam = 'CHANNEL_CODE'; + // static const String accountInfoDbName = 'ACCOUNT_INFO'; + // static const String accountInfoVarName = 'accountInfo'; + // static const String dmpProdcodeDbName = 'DMP_PRODCODE'; + // static const String dmpProdcodeVarName = 'dmpProdcode'; + // static const String dcsSchemcodeDbName = 'DCS_SCHEMCODE'; + // static const String dcsSchemcodeVarName = 'dcsSchemcode'; + // static const String mbmBkmsnumberDbName = 'MBM_BKMSNUMBER'; + // static const String mbmBkmsnumberVarName = 'mbmBkmsnumber'; + // static const String ppcPrcgcodeDbName = 'PPC_PRCGCODE'; + // static const String ppcPrcgcodeVarName = 'ppcPrcgcode'; + // static const String mbmBkmstitleacntDbName = 'MBM_BKMSTITLEACNT'; + // static const String mbmBkmstitleacntVarName = 'mbmBkmstitleacnt'; + // static const String pcrCurrcodeDbName = 'PCR_CURRCODE'; + // static const String pcrCurrcodearName = 'pcrCurrcodear'; + // static const String mbmBkmsbalamountfcDbName = 'MBM_BKMSBALAMOUNTFC'; + // static const String mbmBkmsbalamountfcVarName = 'mbmBkmsbalamountfc'; + // static const String pasAcstcodeDbName = 'PAS_ACSTCODE'; + // static const String pasAcstcodeVarName = 'pasAcstcode'; + // static const String mbmBkmslienamountfcDbName = 'MBM_BKMSLIENAMOUNTFC'; + // static const String mbmBkmslienamountfcVarName = 'mbmBkmslienamountfc'; + // static const String blockedDbName = 'BLOCKED'; + // static const String blockedVarName = 'blocked'; + // static const String noOfTransactionDbName = 'NO_OF_TRANSACTION'; + // static const String noOfTransactiondVarName = 'noOfTransaction'; + // static const String noOfDaysDbName = 'NO_OF_DAYS'; + // static const String noOfDaysVarName = 'noOfDays'; + // static const String noOfMonthsDbName = 'NO_OF_MONTHS'; + // static const String noOfMonthsVarName = 'noOfMonths'; + // static const String fromDateDbName = 'FROM_DATE'; + // static const String fromDateVarName = 'fromDate'; + // static const String toDateDbName = 'TO_DATE'; + // static const String toDateVarName = 'toDate'; + // static const String sgtGntrdateDbName = 'SGT_GNTRDATE'; + // static const String sgtGntrdateVarName = 'sgtGntrdate'; + // static const String sgtGntrvaluedatDbName = 'SGT_GNTRVALUEDAT'; + // static const String sgtGntrvaluedatVarName = 'sgtGntrvaluedat'; + // static const String sgtGntrnumberDbName = 'SGT_GNTRNUMBER'; + // static const String sgtGntrnumberVarName = 'sgtGntrnumber'; + // static const String sgtGntrtimestampDbName = 'SGT_GNTRTIMESTAMP'; + // static const String sgtGntrtimestampVarName = 'sgtGntrtimestamp'; + // static const String transactionDetailInfoDbName = 'TRANSACTION_DETAIL_INFO'; + // static const String transactionDetailInfoVarName = 'transactionDetailInfo'; + // static const String ptrTrancodeDbName = 'PTR_TRANCODE'; + // static const String ptrTrancodeVarName = 'ptrTrancode'; + // static const String sgtGntrdrcrDbName = 'SGT_GNTRDRCR'; + // static const String sgtGntrdrcrVarName = 'sgtGntrdrcr'; + // static const String sgtGntramtfcDbName = 'SGT_GNTRAMTFC'; + // static const String sgtGntramtfcVarName =me = 'SGT_GNTRAMTFC1'; + // static const String sgtGntramtfc1VarName = 'sgtGntramtfc1'; + // static const String sgtGntram 'sgtGntramtfc'; + // static const String sgtGntramtfc1DbNatfc2DbName = 'SGT_GNTRAMTFC2'; + // static const String colorCodeDbName = 'COLOR_CODE'; + // static const String colorCodeVarName = 'colorCode'; + // static const String debitInfoDbName = 'DEBIT_INFO'; + // static const String debitInfoVarName = 'debitInfo'; + // static const String creditInfoDbName = 'CREDIT_INFO'; + // static const String creditInfoVarName = 'creditInfo'; + // static const String pinInfoDbName = 'PIN_INFO'; + // static const String pinInfoVarName = 'pinInfo'; + // static const String operationInfoDbName = 'OPERATION_INFO'; + // static const String operationInfoVarName = 'operationInfo'; + // static const String beneficiaryInfoDbName = 'BENEFICIARY_INFO'; + // static const String beneficiaryInfoVarName = 'beneficiaryInfo'; + // static const String pbtBntpcodeDbName = 'PBT_BNTPCODE'; + // static const String pbtBntpcodeVarName = 'pbtBntpcode'; + // static const String pbtBntpdescDbName = 'PBT_BNTPDESC'; + // static const String pbtBntpdescVarName = 'pbtBntpdesc'; + // static const String ibanDbName = 'IBAN'; + // static const String ibanVarName = 'IBAN'; + // static const String mobileDbName = 'MOBILE'; + // static const String mobileVarName = 'mobile'; + // static const String emailDbName = 'EMAIL'; + // static const String emailVarName = 'email'; + // static const String operationIdDbName = 'OPERATION_ID'; + // static const String operationIdVarName = 'operationId'; + // static const String creditedAtDbName = 'CREDITED_AT'; + // static const String creditedAtVarName = 'creditedAt'; + // static const String statusDbName = 'STATUS'; + // static const String statusVarName = 'status'; + // static const String reconciliationStatusDbName = 'RECONCILIATION_STATUS'; + // static const String reconciliationStatusVarName = 'reconciliationStatus'; + // static const String amountDbName = 'AMOUNT'; + // static const String amountVarName = 'amount'; + // static const String timeZoneDbName = 'TIME_ZONE'; + // static const String timeZoneVarName = 'timeZone'; + // static const String senderInfoDbName = 'SENDER_INFO'; + // static const String senderInfoVarName = 'senderInfo'; + // static const String receiverInfoDbName = 'RECEIVER_INFO'; + // static const String receiverInfoVarName = 'receiverInfo'; + // static const String nameDbName = 'NAME'; + // static const String nameVarName = 'name'; + // static const String idTypeDbName = 'ID_TYPE'; + // static const String idTypeVarName = 'idType'; + // static const String idValueDbName = 'ID_VALUE'; + // static const String idValueVarName = 'idValue'; + // static const String mobileNoDbName = 'MOBILE_NO'; + // static const String mobileNoVarName = 'mobileNo'; + // static const String passKeyDbName = 'PASS_KEY'; + // static const String passKeyVarName = 'passKey'; + // static const String passCodeDbName = 'PASS_CODE'; + // static const String passCodeVarName = 'passCode'; + // static const String pinCodeDbName = 'PIN_CODE'; + // static const String pinCodeVarName = 'pinCode'; + // static const String pinValueDbName = 'PIN_VALUE'; + // static const String pinValueVarName = 'pinValue'; +} diff --git a/lib/app/core/constants/app_assets.dart b/lib/app/core/constants/app_assets.dart new file mode 100644 index 0000000..7454051 --- /dev/null +++ b/lib/app/core/constants/app_assets.dart @@ -0,0 +1,141 @@ +class AppAssets { + static const String ORGANIZATION = "uco"; + + /// Logos + static const lg_uco_logo_white = "assets/$ORGANIZATION/logo/lg_uco_logo_white.svg"; + static const lg_logo_black = "assets/$ORGANIZATION/logo/lg_logo_black.svg"; + static const lg_mfsys = "assets/$ORGANIZATION/logo/lg_mfsys.png"; + static const lg_bank = "assets/$ORGANIZATION/logo/lg_bank.png"; + static const uc_logo = "assets/$ORGANIZATION/logo/uc_logo.png"; + static const ic_dashboard_logo = "assets/$ORGANIZATION/logo/ic_dashboard_logo.svg"; + static const lg_back_arrow = "assets/$ORGANIZATION/logo/lg_back_arrow.svg"; + static const u_receive = "assets/$ORGANIZATION/logo/u_receive.svg"; + static const u_send = "assets/$ORGANIZATION/logo/u_send.svg"; + static const u_shop = "assets/$ORGANIZATION/logo/u_shop.svg"; + static const ic_launcher = "assets/$ORGANIZATION/logo/ic_launcher.png"; + + /// Images + static const img_slider = "assets/$ORGANIZATION/images/img_slider.svg"; + static const img_global = "assets/${ORGANIZATION}/images/img_global.svg"; + static const img_qr = "assets/${ORGANIZATION}/images/im_qr.svg"; + + ///Icons ic_desposit_account_arrow + static const ic_pakistan = "assets/${ORGANIZATION}/icons/ic_pakistan.png"; + static const ic_arrow_down = "assets/${ORGANIZATION}/icons/ic_arrow_down.svg"; + static const ic_client = "assets/$ORGANIZATION/icons/ic_client.png"; + static const ic_contact_us = "assets/$ORGANIZATION/icons/ic_contact_us.png"; + static const ic_cyber_security = "assets/$ORGANIZATION/icons/ic_cyber_security.svg"; + static const ic_security = "assets/$ORGANIZATION/icons/ic_security.png"; + static const ic_QR = "assets/$ORGANIZATION/icons/ic_QR.png"; + static const ic_cross = "assets/$ORGANIZATION/icons/ic_cross.svg"; + static const ic_email = "assets/$ORGANIZATION/icons/ic_email.svg"; + static const ic_phone = "assets/$ORGANIZATION/icons/ic_phone.svg"; + static const ic_clock_circle = "assets/$ORGANIZATION/icons/ic_clock_circle.svg"; + static const ic_success_tick = "assets/$ORGANIZATION/icons/ic_success_tick.svg"; + + static const ic_cheque_management = "assets/$ORGANIZATION/icons/ic_cheque_management.svg"; + static const ic_activity = "assets/$ORGANIZATION/icons/ic_activity.svg"; + static const ic_close = "assets/$ORGANIZATION/icons/ic_close.svg"; + + // static const ic_customer_service = "assets/$ORGANIZATION/icons/ic_customer_service.svg"; + static const ic_location = "assets/$ORGANIZATION/icons/ic_location.svg"; + static const ic_logout = "assets/$ORGANIZATION/icons/ic_logout.svg"; + static const ic_management = "assets/$ORGANIZATION/icons/ic_management.svg"; + static const ic_money_management = "assets/$ORGANIZATION/icons/ic_money_management.svg"; + static const ic_night_mode = "assets/$ORGANIZATION/icons/ic_night_mode.svg"; + static const ic_setting = "assets/$ORGANIZATION/icons/ic_setting.svg"; + static const ic_social_network = "assets/$ORGANIZATION/icons/ic_social_network.svg"; + static const ic_u_send = "assets/$ORGANIZATION/icons/ic_u_send.svg"; + static const ic_user = "assets/$ORGANIZATION/icons/ic_user.svg"; + static const ic_white_color_user = "assets/$ORGANIZATION/icons/ic_white_color_user.svg"; + static const ic_person = "assets/$ORGANIZATION/icons/ic_user.svg"; + static const ic_accounts = "assets/$ORGANIZATION/icons/ic_accounts.svg"; + static const ic_cash_bottombar = "assets/$ORGANIZATION/icons/ic_cash_bottombar.svg"; + static const ic_shoping = "assets/$ORGANIZATION/icons/ic_shoping.svg"; + static const ic_money_send = "assets/$ORGANIZATION/icons/ic_money_send.svg"; + static const lg_dialog_logo = "assets/$ORGANIZATION/logo/lg_dialog_logo.svg"; + static const sending_icon = "assets/$ORGANIZATION/icons/sending_icon.svg"; + static const ic_snding_money = "assets/$ORGANIZATION/icons/ic_snding_money.svg"; + static const ic_u_cash = "assets/$ORGANIZATION/icons/ic_u_cash.svg"; + static const ic_u_recive = "assets/$ORGANIZATION/icons/ic_u_recive.svg"; + static const ic_u_shop = "assets/$ORGANIZATION/icons/ic_u_shop.svg"; + static const img_round_dashboard_card = "assets/$ORGANIZATION/images/img_round_dashboard_card.svg"; + static const img_debet = "assets/$ORGANIZATION/images/img_debet.svg"; + static const ic_camera = "assets/$ORGANIZATION/icons/ic_camera.svg"; + static const ic_next = "assets/$ORGANIZATION/icons/ic_next.svg"; + + static const ic_feature_icon = "assets/$ORGANIZATION/icons/ic_feature_icon.svg"; + static const ic_country_flag = "assets/$ORGANIZATION/icons/ic_country_flag.svg"; + static const ic_desposit_account_arrow = "assets/$ORGANIZATION/icons/ic_desposit_account_arrow.svg"; + static const ic_saving_account = "assets/$ORGANIZATION/icons/ic_saving_account.svg"; + static const ic_back_arrow_appbar = "assets/$ORGANIZATION/icons/ic_back_arrow_appbar.svg"; + + static const kprogresshud_spinner = "assets/uco/icons/ic_kprogresshud_spinner.png"; + + static const ic_electricity = "assets/${ORGANIZATION}/icons/ic_electricity.png"; + static const ic_gas = "assets/${ORGANIZATION}/icons/ic_gas.png"; + static const ic_internet = "assets/${ORGANIZATION}/icons/ic_internet.png"; + static const ic_ptcl = "assets/${ORGANIZATION}/icons/ic_ptcl.svg"; + static const ic_water = "assets/${ORGANIZATION}/icons/ic_water.png"; + static const ic_card = "assets/${ORGANIZATION}/icons/ic_card.svg"; + static const ic_government = "assets/${ORGANIZATION}/icons/ic_government.png"; + static const ic_multan = "assets/${ORGANIZATION}/icons/ic_multan.png"; + static const ic_khan = "assets/${ORGANIZATION}/icons/ic_khan.png"; + static const ic_ke = "assets/${ORGANIZATION}/icons/ic_ke.png"; + static const ic_kc = "assets/${ORGANIZATION}/icons/ic_kc.png"; + static const ic_removeImage = "assets/${ORGANIZATION}/icons/ic_removeImage.svg"; + static const ic_check_status = "assets/${ORGANIZATION}/icons/ic_check_status.svg"; + static const ic_cheque_deposit = "assets/${ORGANIZATION}/icons/ic_cheque_deposit.svg"; + static const ic_activation = "assets/${ORGANIZATION}/icons/ic_activation.svg"; + static const ic_request = "assets/${ORGANIZATION}/icons/ic_request.svg"; + static const ic_cheque = "assets/${ORGANIZATION}/icons/ic_cheque.svg"; + static const ic_download = "assets/${ORGANIZATION}/icons/ic_download.svg"; + static const ic_share = "assets/${ORGANIZATION}/icons/ic_share.svg"; + + static const arrow = "assets/$ORGANIZATION/icons/arrow.svg"; + static const ic_manage_account = "assets/$ORGANIZATION/icons/ic_manage_account.svg"; + static const bankDetails = "assets/$ORGANIZATION/icons/bankDetails.svg"; + static const changePassoword = "assets/$ORGANIZATION/icons/changePassoword.svg"; + static const inviteFriendsUco = "assets/$ORGANIZATION/icons/inviteFriendsUco.svg"; + static const personalDetails = "assets/$ORGANIZATION/icons/personal_details.svg"; + static const ic_sort = "assets/$ORGANIZATION/icons/ic_sort.png"; + static const ic_featured = "assets/$ORGANIZATION/icons/ic_featured.svg"; + static const ic_congratulations = "assets/$ORGANIZATION/icons/ic_congratulations.svg"; + static const ic_correct_icon = "assets/$ORGANIZATION/icons/ic_correct_icon.svg"; + + static const ic_arrow = "assets/$ORGANIZATION/icons/ic_arrow.svg"; + + static const icCloseDash = "assets/$ORGANIZATION/icons/_ic_close_dashboard.svg"; + + static String use_flag = "assets/$ORGANIZATION/icons/use_flag.png"; + + static String euro_flag = "assets/$ORGANIZATION/icons/euro_flag.png"; + static String gbp_flag = "assets/$ORGANIZATION/icons/gbp_flag.png"; + static String aud_flag = "assets/$ORGANIZATION/icons/aud_flag.png"; + static String ind_flag = "assets/$ORGANIZATION/icons/ind_flag.png"; + + static String drop_down_ic = "assets/uco/icons/drop_down_ic.png"; + static const ic_debit_card = "assets/$ORGANIZATION/icons/ic_debit_card.svg"; + static const ic_bank = "assets/$ORGANIZATION/icons/ic_bank.svg"; + static const ic_general_ledger = "assets/$ORGANIZATION/icons/ic_general_ledger.svg"; + static const ic_home_icon = "assets/$ORGANIZATION/icons/ic_home_icon.svg"; + static const ic_tick_option = "assets/$ORGANIZATION/icons/ic_tick_option.svg"; + static const ic_cross_option = "assets/$ORGANIZATION/icons/ic_cross_option.svg"; + + static var ic_sui_gas = "assets/$ORGANIZATION/icons/suigas.svg"; + static var ic_filter_statement = "assets/$ORGANIZATION/icons/ic_filter_statement.svg"; + static var ic_u_receive_menu = "assets/$ORGANIZATION/icons/ic_u_receive_menu.svg"; + static var ic_cross_white = "assets/$ORGANIZATION/icons/ic_cross_white.svg"; + static var ic_sub_accounts = "assets/$ORGANIZATION/icons/ic_sub_accounts.svg"; + static var sending_icon_icon = "assets/$ORGANIZATION/icons/sending_icon_icon.svg"; + static var bankAccountDetails = "assets/$ORGANIZATION/icons/bankAccountDetails.svg"; + static var ic_language = "assets/$ORGANIZATION/icons/ic_language.svg"; + static var ic_daily_transaction = "assets/$ORGANIZATION/icons/ic_daily_transaction.svg"; + static var ic_customer_service = "assets/$ORGANIZATION/icons/ic_customer_service.svg"; + static var ic_bill = "assets/$ORGANIZATION/icons/ic_bill.svg"; + static var ic_arrow_down_icon = "assets/$ORGANIZATION/icons/ic_arrow_down_icon.png"; + static var ic_select_contact = "assets/$ORGANIZATION/icons/ic_select_contact.svg"; + static var ic_bank_transfer = "assets/$ORGANIZATION/icons/ic_bank_transfer.svg"; + static var ic_add_new_Account = "assets/$ORGANIZATION/icons/ic_add_new_Account.png"; + static var ic_warning = "assets/$ORGANIZATION/icons/ic_warning.png"; +} diff --git a/lib/app/core/constants/app_contants.dart b/lib/app/core/constants/app_contants.dart new file mode 100644 index 0000000..0d48b08 --- /dev/null +++ b/lib/app/core/constants/app_contants.dart @@ -0,0 +1,88 @@ +class AppConstants { + + // Pin Type + static const String PIN_TYPE_SIGNUP = "01"; + static const String PIN_TYPE_LOGIN = "02"; + static const String PIN_TYPE_Transaction = "03"; + + + // User Role + static const String ROLE_USER = "USER"; + static const String ROLE_ADMIN = "ADMIN"; + + + // Identification type + static const String IDEN_TYPE_CNIC = "01"; + static const String IDEN_TYPE_PASSPORT = "02"; + static const String IDEN_TYPE_DRIVING_LICIENCE = "03"; + + + /// ------------------------- DashBoard Drawer + static const ID_CHANGE_THEME = "ID_CHANGE_THEME"; + static const ID_MY_ACCOUNT = "ID_MY_ACCOUNT"; + static const ID_BILL_MANAGEMENT = "ID_BILL_MANAGEMENT"; + static const ID_CHEQUE_MANAGEMENT = "ID_CHEQUE_MANAGEMENT"; + static const ID_U_SEND = "ID_U_SEND"; + static const ID_INTERNAL_TRANSACTION = "ID_INTERNAL_TRANSACTION"; + static const ID_BENEFICIARY_MANAGEMENT = "ID_BENEFICIARY_MANAGEMENT"; + static const ID_PROFILE = "ID_PROFILE"; + static const ID_AGENT_LOCATION = "ID_AGENT_LOCATION"; + static const ID_ACCOUNT_STATEMENT = "ID_ACCOUNT_STATEMENT"; + static const ID_SUPPORT = "ID_SUPPORT"; + static const ID_USER_ACTIVITY = "ID_USER_ACTIVITY"; + static const ID_LOGOUT = "ID_LOGOUT"; + static const ID_USER_PROFILE = "ID_USER_PROFILE"; + static const ID_APP_SETTING = "ID_APP_SETTING"; + static const ID_PRIVACY_POLICY = "ID_PRIVACY_POLICY"; + static const ID_VERSION = "ID_VERSION"; + static const SELECTED_LOCALE = "selectedLocale"; + static const SELECTED_CONTACT = "selectedContact"; + static const IS_RTL = "isRTL"; + static const ID_ABOUT_US = "ID_ABOUT_US"; + static const ID_CAREER = "ID_CAREER"; + + static var SIGN_UP_FIRST_STEP_DATA = "SIGN_UP_FIRST_STEP_DATA"; + static var SIGN_UP_SECOND_STEP_DATA = "SIGN_UP_SECOND_STEP_DATA"; + static const IS_DARK_MODE = "isDarkMode"; + static const IS_FINGER_PRINT_ENABLED = "isFingrPrinterEnabled"; + + + static const SEND_TRANS_STEP1_DATA = "SEND_TRANS_STEP1_DATA"; + static const SEND_TRANS_PIN_REQUEST = "SEND_TRANS_PIN_REQUEST"; + static const INTERNAL_TRANSACTION_PIN_REQUEST = "INTERNAL_TRANSACTION_PIN_REQUEST"; + static const EXCHANGE_RATE = "EXCHANGE_RATE"; + + /// Request constants + static const FETCH_ACCOUNT_DETAILS = "FETCH_ACCOUNT_DETAILS"; + static const SEND_TRANSACTION_STEP_1 = "SEND_TRANSACTION_STEP_1"; + static const SEND_TRANSACTION_STEP_2 = "SEND_TRANSACTION_STEP_2"; + static const ADD_NEW_BENEFICIARY = "ADD_NEW_BENEFICIARY"; + static const UPLOAD_USER_PROFILE_PICTURE = "UPLOAD_USER_PROFILE_PICTURE"; + static const GET_LOGIN_OTP = "GET_LOGIN_OTP"; + static const VALIDATE_LOGIN_PIN = "VALIDATE_LOGIN_PIN"; + static const FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS = "FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS"; + static const FETCH_EXCHANGE_RATE = "FETCH_EXCHANGE_RATE"; + static const FETCH_ACCOUNT_IQUIRY = "FETCH_ACCOUNT_IQUIRY"; + static const FETCH_ALL_BENEFICIARY = "FETCH_ALL_BENEFICIARY"; + static const DELETE_BENEFICIARY = "DELETE_BENEFICIARY"; + static const CREATE_TRANSACTION_PIN = "CREATE_TRANSACTION_PIN"; + static const CHANGE_TRANSACTION_PIN = "CHANGE_TRANSACTION_PIN"; + static const GENERATE_REPORTS = "GENERATE_REPORTS"; + static const SIGNUP_STEP_1 = "SIGNUP_STEP_1"; + static const SIGUP_STEP_2 = "SIGUP_STEP_2"; + static const SIGUP_STEP_3 = "SIGUP_STEP_3"; + static const CHANGE_PASSWORD_SEND_OTP = "CHANGE_PASSWORD_SEND_OTP"; + static const CHANGE_PASSWORD = "CHANGE_PASSWORD"; + static const GET_PENDING_TRANSITION = "GET_PENDING_TRANSITION"; + static const ACCEPT_RECEIVE_TRANSACTION = "ACCEPT_RECEIVE_TRANSACTION"; + static const REVERSE_TRANSACTION = "REVERSE_TRANSACTION"; + static const FETCH_ACCOUNT_STATEMENT = "FETCH_ACCOUNT_STATEMENT"; + static const DEVICE_NAME = "Mobile"; + static const FETCH_USER_ACTIVITY = "FETCH_USER_ACTIVITY"; + static const FETCH_DEPOSIT_PRODUCTS = "FETCH_DEPOSIT_PRODUCTS"; + static const FETCH_GLS_ACCOUNTS = "FETCH_GLS_ACCOUNTS"; + static const ADD_NEW_ACCOUNT = "ADD_NEW_ACCOUNT"; + static const CREATE_TRANSACTION_PIN_OTP = "CREATE_TRANSACTION_PIN_OTP"; + static const CHANGE_TRANSACTION_PIN_OTP = "CHANGE_TRANSACTION_PIN_OTP"; + +} diff --git a/lib/app/core/constants/form_field_constants.dart b/lib/app/core/constants/form_field_constants.dart new file mode 100644 index 0000000..22f677c --- /dev/null +++ b/lib/app/core/constants/form_field_constants.dart @@ -0,0 +1,30 @@ +import 'package:flutter/cupertino.dart'; + +class FormFieldConstants { + static FormFieldConstants instance() { + return _instance; + } + + static final FormFieldConstants _instance = FormFieldConstants._internal(); + + FormFieldConstants._internal(); + + factory FormFieldConstants() { + return _instance; + } + + final Map> _keys = {}; + final Map _controllers = {}; + + TextEditingController getController(String keyName) { + return _controllers[keyName] ??= TextEditingController(); // Assign if not exist + } + + GlobalKey getFormKey(String keyName) { + return _keys[keyName] ??= GlobalKey(); // Assign if not exist + } + void clearKeysForScreen(String screenPrefix) { + _keys.removeWhere((key, value) => key.startsWith(screenPrefix)); + _controllers.removeWhere((key, value) => key.startsWith(screenPrefix)); + } +} diff --git a/lib/app/core/constants/translation_keys.dart b/lib/app/core/constants/translation_keys.dart new file mode 100644 index 0000000..5affafd --- /dev/null +++ b/lib/app/core/constants/translation_keys.dart @@ -0,0 +1,344 @@ +import 'package:get/get.dart'; + +class TranslationKeys { + static String textUserActivityTitle = "textUserActivityTitle"; + static String textAddBeneficiary = "textAddBeneficiary"; + static String textWarningContent = "textWarningContent"; + + static String textUserActivityChannel = "textUserActivityChannel"; + static String textReferenceCode = "textReferenceCode"; + + static var textUserActivityDevice = "textUserActivityDevice"; + static var textInternetConnectivity = "textInternetConnectivity"; + static var textInternalAccountTransaction = "textInternalAccountTransaction"; + + static var textPay = "textPay"; + static var textTransferAmount = "textTransferAmount"; + static var textAddToBeneficiary = "textAddToBeneficiary"; + static var textDelete = "textDelete"; + + static String changepassword = "changepassword"; + static String textAddAccount = "textAddAccount"; + static String textCreateAccount = "textCreateAccount"; + static String textReverse = "textReverse"; + + static String textChangePassword = "textChangePassword"; + static String textEnterEmail = "textEnterEmail"; + static String textCongratulationsContent = "textCongratulationsContent"; + + static String textSelectFromDateAndProceed = "textSelectFromDateAndProceed"; + static String transPakGasAgency = "transPakGasAgency"; + static String transSuiGas = "transSuiGas"; + static String transMinerva = "transMinerva"; + static String transNestle = "transNestle"; + static String transAquaFujitenma = "transAquaFujitenma"; + static String transPepsiCo = "transPepsiCo"; + static String transFiber = "transFiber"; + static String transZong = "transZong"; + static String textPasswordPattern = "textPasswordPattern"; + static String textOurFee = "textOurFee"; + static String textTotalAmountWellConvert = "textTotalAmountWellConvert"; + static String textGuaranteedExchnageRate = "textGuaranteedExchnageRate"; + static String textSelectYourGLSAccount = "textSelectYourGLSAccount"; + static String textGlsAccounts = "textGlsAccounts"; + static String textEnterMessage = "textEnterMessage"; + + static String continueText = "Continue"; + static String ERR_CONNECTION = "ERR_CONNECTION"; + + static String makeTranslation(String key) { + return key.tr; + } + + static String textWelcomeToJoin = "textWelcomeToJoin"; + static String textShare = "textShare"; + static String textIntroDescription = "textIntroDescription"; + static String textLogin = "textLogin"; + static String textRegister = "textRegister"; + static String textFindUAgent = "textFindUAgent"; + static String textQRPay = "textQRPay"; + static String textHelp = "textHelp"; + static String textContactUs = "textContactUs"; + static String textGetInTouch = "textGetInTouch"; + static String textEmail = "textEmail"; + static String textPhone = "textPhone"; + static String textOTPDescription = "textOTPDescription"; + static String textOTP = "textOTP"; + static String textOTPValid = "textOTPValid"; + static String textResend = "textResend"; + static String textVerify = "textVerify"; + static String textCongratulations = "textCongratulations"; + static String textOTPMessage = "textOTPMessage"; + static String resetPasswordMessage = "resetPasswordMessage"; + static String textContinue = "textContinue"; + static String textAccountTitle = "textAccountTitle"; + static String textAccountSession = "textAccountSession"; + static String textSuccess = "textSuccess"; + static String textOK = "textOK"; + static String textWarning = "textWarning"; + static String textCancel = "textCancel"; + static String textConformation = "textConformation"; + static String textLogOutContent = "textLogOutContent"; + static String textManage = "textManage"; + static String textLogout = "textLogout"; + static String textVersion = "textVersion"; + static String textMyAccount = "textMyAccount"; + static String textBillManagement = "textBillManagement"; + static String textChequeManagement = "textChequeManagement"; + static String textUSend = "textUSend"; + static String textUReceived = "textUReceived"; + static String textBeneficiaryManagement = "textBeneficiaryManagement"; + static String textAgentLocation = "textAgentLocation"; + static String textAccountStatement = "textAccountStatement"; + static String textSupport = "textSupport"; + static String textUserProfile = "textUserProfile"; + static String textUserActivity = "textUserActivity"; + static String textLogOut = "textLogOut"; + static String textUCash = "textUCash"; + static String textUShop = "textUShop"; + static String textOverView = "textOverView"; + static String textDashboardWelcomeUser = "textDashboardWelcomeUser"; + static String textTotalAvailableFunds = "textTotalAvailableFunds"; + static String textTotalAvailableBalance = "textTotalAvailableBalance"; + static String textTotalAvailableBalanceInWords = "textTotalAvailableBalanceInWords"; + static String textAccountNumber = "textAccountNumber"; + static String textPleaseSelectAccount = "textPleaseSelectAccount"; + static String textStatementDetails = "textStatementDetails"; + static String textBalance = "textBalance"; + static String textUPrimary = "textUPrimary"; + static String textUSave = "textUSave"; + static String textUChaChing = "textUChaChing"; + static String textAboutUs = "textAboutUs"; + static String textCareer = "textCareer"; + static String textWHY = "textWHY"; + static String textWHYDescription = "textWHYDescription"; + static String textWHAT = "textWHAT"; + static String textWHATDescription = "textWHATDescription"; + static String textWHO = "textWHO"; + static String textWHODescription = "textWHODescription"; + static String textJobTitle = "textJobTitle"; + static String textApply = "textApply"; + static String textOfficeAddress = "textOfficeAddress"; + static String textJobSkills = "textJobSkills"; + static String textSelectPersonalAccount = "textSelectPersonalAccount"; + static String textRecipientDetail = "textRecipientDetail"; + static String textPhoneNumber = "textPhoneNumber"; + static String textRecipientCardName = "textRecipientCardName"; + static String textSelectCurrency = "textSelectCurrency"; + static String textSendingAmount = "textSendingAmount"; + static String textExchangeRate = "textExchangeRate"; + static String textMessageMemo = "textMessageMemo"; + static String textSend = "textSend"; + static String textClear = "textClear"; + static String textPermissionDenied = "textPermissionDenied"; + static String textMyProfile = "textMyProfile"; + static String textNotFound = "textNotFound"; + static String textRecipient = "textRecipient"; + static String textHome = "textHome"; + static String textCurrency = "textCurrency"; + static String textMessage = "textMessage"; + static String textConfirm = "textConfirm"; + static String textEndingBalance = "textEndingBalance"; + static String textPendingRemittance = "textPendingRemittance"; + static String textReceived = "textReceived"; + static String textPinCode = "textPinCode"; + static String textBack = "textBack"; + static String textCancelDescription = "textCancelDescription"; + static String textYes = "textYes"; + static String textErrorRequired = "textErrorRequired"; + static String textUserName = "textUserName"; + static String textPassword = "textPassword"; + static String textConfirmPassword = "textConfirmPassword"; + static String textEmailID = "textEmailID"; + static String textCellNumber = "textCellNumber"; + static String textNext = "textNext"; + static String textName = "textName"; + static String textAddress = "textAddress"; + static String textIdentityNumber = "textIdentityNumber"; + static String textSSNTaxPayerID = "textSSNTaxPayerID"; + static String textPassportAlienID = "textPassportAlienID"; + static String textChooseDocumentType = "textChooseDocumentType"; + static String textCNIC = "textCNIC"; + static String textDivingLicense = "textDivingLicense"; + static String textPassport = "textPassport"; + static String textDocumentsDescription = "textDocumentsDescription"; + static String textFront = "textFront"; + static String textSkipKYC = "textSkipKYC"; + static String textSignUpDescriptionDailog = "textSignUpDescriptionDailog"; + static String textNotRegisterUser = "textNotRegisterUser"; + static String textRegisterNow = "textRegisterNow"; + static String textSingUp = "textSingUp"; + static String textUploadKYC = "textUploadKYC"; + static String textTransactionHistory = "textTransactionHistory"; + static String textSelectOption = "textSelectOption"; + static String textSearch = "textSearch"; + + /// import from Include app + static String textMapLocationTitle = "textMapLocationTitle"; + static String textNormalMap = "textNormalMap"; + static String textSatelliteMap = "textSatelliteMap"; + static String textHybridMap = "textHybridMap"; + static String textMapContactNumber = "textMapContactNumber"; + static String transUtilityBillCategory = "transUtilityBillCategory".tr; + static String transUtilityBill = "transUtilityBill"; + static String textSelectBillType = "textSelectBillType"; + static String transUtilityElectricity = "transUtilityElectricity"; + static String transUtilityGas = "transUtilityGas"; + static String transUtilityInternet = "transUtilityInternet"; + static String transUtilityPTCL = "transUtilityPTCL"; + static String transUtilityWater = "transUtilityWater"; + static String transUtilityCreditCard = "transUtilityCreditCard"; + static String textSelectCompany = "textSelectCompany"; + static String transUtilityAJKBARKIYAT = "transUtilityAJKBARKIYAT".tr; + static String transUtilityFESCO = "transUtilityFESCO".tr; + static String transUtilityGBBARKIYAT = "transUtilityGBBARKIYAT".tr; + static String transUtilityGEPCO = "transUtilityGEPCO".tr; + static String transUtilityHESCO = "transUtilityHESCO".tr; + static String transUtilityIESCO = "transUtilityIESCO".tr; + static String textChequeBookActivation = "textChequeBookActivation"; + static String textChequeBookActivationDialogMsg = "textChequeBookActivationDialogMsg"; + static String textActivationContent = "textActivationContent"; + static String textActivationContentPart = "textActivationContentPart"; + static String textAccount = "textAccount"; + + //static String textAccountNumber = "textAccountNumber"; + static String textBillDetailCustomerName = "textBillDetailCustomerName"; + static String textFirstLeaf = "textFirstLeaf"; + static String textEnterChequeNumber = "textEnterChequeNumber"; + static String textLastLeaf = "textLastLeaf"; + static String textChequeRequestDetail = "textChequeRequestDetail"; + static String textChequeBookRequestContent = "textChequeBookRequestContent"; + static String textLeave20 = "textLeave20"; + static String textLeaves = "textLeaves"; + static String textGet = "textGet"; + static String textLeave50 = "textLeave50"; + static String textLeave100 = "textLeave100"; + static String textChange = "textChange"; + static String textDeliveryAddress = "textDeliveryAddress"; + static String textChequeBookRequestAddress = "textChequeBookRequestAddress"; + static String textCharges = "textCharges"; + static String textScheduleCharges = "textScheduleCharges"; + static String textDate = "textDate"; + static String textDateContent = "textDateContent"; + static String textRequestSummary = "textRequestSummary"; + static String textNumberofLeaves = "textNumberofLeaves"; + static String textQueryContent = "textQueryContent"; + static String textDeposit = "textDeposit"; + static String textChequeDeposit = "textChequeDeposit"; + static String textChequeStatusContent = "textChequeStatusContent"; + static String textDepositToChequing = "textDepositToChequing"; + static String text1000 = "text1000"; + static String textMax300000 = "textMax300000"; + static String textSelectAccount = "textSelectAccount"; + static String textFrontOfCheque = "textFrontOfCheque"; + static String textBackofCheque = "textBackofCheque"; + static String textTryAgain = "textTryAgain"; + static String textChequeStatus = "textChequeStatus"; + static String textChequeActivation = "textChequeActivation"; + static String textChequeRequest = "textChequeRequest"; + static String textChequeRequestContent = "textChequeRequestContent"; + static String textChequeNumber = "textChequeNumber"; + static String textChequeStatusHistory = "textChequeStatusHistory"; + static String textChequeStatusHistoryContent = "textChequeStatusHistoryContent"; + static String textChequeStatusCheckNumber = "textChequeStatusCheckNumber"; + static String textChequeStatusHistoryRefNo = "textChequeStatusHistoryRefNo"; + static String textChequeStatusHistorySuccess = "textChequeStatusHistorySuccess"; + static String textChequeStatusHistoryCancel = "textChequeStatusHistoryCancel"; + static String textPTCLLandLine = "textPTCLLandLine"; + static String textSelectAccountDetails = "textSelectAccountDetails"; + static String textCreditCard = "textCreditCard"; + static String textCreditCardNumber = "textCreditCardNumber"; + static String textAmountDebit = "textAmountDebit"; + static String textEnterConsumerName = "textEnterConsumerName"; + static String textTotalAmount = "textTotalAmount"; + static String textEnterAmount = "textEnterAmount"; + static String textBillDetails = "textBillDetails"; + static String textBillConsumerName = "textBillConsumerName"; + static String textBillAmount = "textBillAmount"; + static String textDueDate = "textDueDate"; + static String textAmountDueAfterDueDate = "textAmountDueAfterDueDate"; + static String textBillStatus = "textBillStatus"; + static String textBillDetailZero = "textBillDetailZero"; + static String textBillDetailDate = "textBillDetailDate"; + static String textBillDetailUnPaid = "textBillDetailUnPaid"; + static String textPayNow = "textPayNow"; + static String textBillDetailContent = "textBillDetailContent"; + static String textBillDetailBalance = "textBillDetailBalance"; + static String textBillDetailBillAmount = "textBillDetailBillAmount"; + static String textBillDetailBillDueDate = "textBillDetailBillDueDate"; + static String textBillDetailBillAmountDue = "textBillDetailBillAmountDue"; + static String textBillDetailBillAfterDueDate = "textBillDetailBillAfterDueDate"; + static String textBillDetailBillStatus = "textBillDetailBillStatus"; + static String textProfileHey = "textProfileHey"; + static String textProfileUsername = "textProfileUsername"; + static String textAppSettingTitle = "textAppSettingTitle"; + static String textLanguagesTitle = "textLanguagesTitle"; + static String textDarkModeContent = "textDarkModeContent"; + static String textFingerPrintTitle = "textFingerPrintTitle"; + static String textFingerPrintContent = "textFingerPrintContent"; + static String textPasswordChangeTitle = "textPasswordChangeTitle"; + static String textPasswordChangeContent = "textPasswordChangeContent"; + static String textTermOfService = "textTermOfService"; + static String textPrivacy = "textPrivacy"; + static String textInviteFriends = "textInviteFriends"; + static String textDialogConformation = "textDialogConformation"; + static String textDialogContent = "textDialogContent"; + static String textSignOut = "textSignOut"; + static String textSelectYourOption = "textSelectYourOption"; + static String textLanguageEnglish = "textLanguageEnglish"; + static String textLanguageArabic = "textLanguageArabic"; + static String textLanguageUrdu = "textLanguageUrdu"; + static String textNoSelect = "textNoSelect"; + static String textMyAccountTitle = "textMyAccountTitle"; + static String textMyAccountAccountTitle = "textMyAccountAccountTitle"; + static String textMyAccountAccountNumber = "textMyAccountAccountNumber"; + static String textMyAccountBranchCode = "textMyAccountBranchCode"; + static String textMyAccountAccountOpeningDate = "textMyAccountAccountOpeningDate"; + static String textAppSetting = "textAppSetting"; + static String textLoginTitle = "textLoginTitle"; + static String textInvalidFingerprint = "textInvalidFingerprint"; + static String textDailyTransactionLimit = "textDailyTransactionLimit"; + static String textChangeTransactionPin = "textChangeTransactionPin"; + static String textQRSetting = "textQRSetting"; + static String textTransactionLimit = "textTransactionLimit"; + static String textTransactionPin = "textTransactionPin"; + static String textOldLimit = "textOldLimit"; + static String textMaximumLengthContent = "textMaximumLengthContent"; + static String textLimitNoteContent = "textLimitNoteContent"; + static String textCurrentDailyLimit = "textCurrentDailyLimit"; + static String textDone = "textDone"; + static String textPinOTPMessage = "textPinOTPMessage"; + static String textYourUCOQR = "textYourUCOQR"; + static String textUCOQRContent = "textUCOQRContent"; + static String textQrAccountName = "textQrAccountName"; + static String textQrAccountNumber = "textQrAccountNumber"; + static String textShareQRCode = "textShareQRCode"; + static String textSavetoGallery = "textSavetoGallery"; + static String textNotifications = "textNotifications"; + static String textFilter = "textFilter"; + static String textCreateTransactionPin = "textCreateTransactionPin"; + static String textPleaseCreatenewtransactionpin = "textPleaseCreatenewtransactionpin"; + static String textConfirmTransactionPin = "textConfirmTransactionPin"; + static String textOldTransactionPin = "textOldTransactionPin"; + static String textNotificationDetails = "textNotificationDetails"; + static String textNotificationDetailsContent = "textNotificationDetailsContent"; + static String textError = "textError"; + static String textDescription = "textDescription"; + static String textInform = "textInform"; + static String textConfirmTransaction = "textConfirmTransaction"; + static String textHowdoyouwanttopay = "textHowdoyouwanttopay"; + static String textDebitCard = "textDebitCard"; + static String textDebitCardContent = "textDebitCardContent"; + static String textBankTransfer = "textBankTransfer"; + static String textGeneralLedger = "textGeneralLedger"; + static String transAddMoney = "transAddMoney"; + static String textGLCode = "textGLCode"; + static String textFaqs = "textFaqs"; + static String textHowCanIHelpYou = "textHowCanIHelpYou"; + static String textExploreAllArticles = "textExploreAllArticles"; + static String textFirstName = "textFirstName"; + static String textLastName = "textLastName"; + + + +} \ No newline at end of file diff --git a/lib/app/core/constants/url_constants.dart b/lib/app/core/constants/url_constants.dart new file mode 100644 index 0000000..29aa807 --- /dev/null +++ b/lib/app/core/constants/url_constants.dart @@ -0,0 +1,100 @@ +import 'package:uco_mobile_poc/app/core/utils/url_encryption.dart'; + +class UrlContants { + static const baseUrl = "http://192.168.0.250:8888"; + // FMFI + // static const baseUrl = "https://uco.mfsys.ca"; // FMFI + // public interface SecurityURI { + // String REGISTER_USER = "/security/auth/user/register"; + // String LOGIN = "/security/auth/user/authenticate"; + // String REFRESH_TOKEN = "/security/auth/refresh-token"; + // String SIGNUP_OTP = "/security/auth/signup-otp"; + // String VERIFY_SINGUP_OTP = "/security/auth/verifysignup-otp"; + // String CHANGE_PASSWORD = "/security/user/changePassword"; + // String RESET_PASSWORD = "/security/user/resetPassword"; + // String GENERATE_INTERNAL_TOKEN = "/security/auth/generateInternalToken"; + // } + /// Encrypted Url constant.... + // static final UrlEncryption encryption = UrlEncryption(); + // static final String encryptedUrl = encryption.encryptData('https://uco.mfsys.ca'); + // static final String baseUrl =''; + + static final REFRESH_TOKEN = "$baseUrl/refreshtoken"; + static final LOGIN = "$baseUrl/security/auth/user/authenticate"; + static final LOGIN_OTP = "$baseUrl/security/auth/verifylogin-otp"; + static final RESEND_OTP = "$baseUrl/customer/login/otp-send"; + static final REGISTER = "$baseUrl/customer/register"; + static final VERIFY_ID = "$REGISTER/checkid"; + static final VERIFY_ACCOUNT_NO = "$REGISTER/checkaccountno"; + static final PIN_VERIFY = "$REGISTER/pin-verify"; + static final SET_PASSWORD = "$baseUrl/customer/set-password"; + static final ACCOUNT_DETAILS = "$baseUrl/uco/depositAccounts"; + static final ACCOUNT_INQUIRY = "$baseUrl/uco/accountInquiry"; + + static final EXCHANGE_RATE = "$baseUrl/uco/fetchExchangeRate"; + + static final FETCH_PAYMENT_PURPOSE = "$baseUrl/getPurposes"; + static final LOAN_ACCOUNT_DETAILS = "$baseUrl/account/indvdetails"; + static final ACCOUNT_TRANSACTIONS = "$baseUrl/uco/accountStatement"; + static final LOAN_ACCOUNT_TRANSACTIONS = "$baseUrl/account/loan/history"; + + static final BENEFICIARY_ACCOUNTS = "$baseUrl/beneficiary"; + static final ACTIVITY_DETAILS = "$baseUrl/account/activity"; + static final SEND_TRANSACTION_STEP1 = "$baseUrl/uco/sendDrTranOtpAndVerifyTranPin"; + static final SEND_TRANSACTION_STEP2 = "$baseUrl/uco/submitDrTransaction"; + static final UPLOAD_USER_PROFILE_PICTURE = "$baseUrl/uco/updateCustomerProfile"; + + static final CREATE_TRANSACTION_PIN_OTP = "$baseUrl/uco/createTransactionPin"; + static final CREATE_TRANSACTION_PIN = "$baseUrl/uco/verifyTransactionPin"; + static final CHANGE_TRANSACTION_PIN = "$baseUrl/uco/changeTransactionPin"; + static final BENEFICIARY_PIN = "$baseUrl/beneficiary"; + static final GENERATE_REPORTS = "$baseUrl/uco/generateReport"; + static final DELETE_BENEFICIARYT = "$baseUrl/beneficiary"; + + static final CHANGE_PASSWORD_SEND_OTP = "$baseUrl/security/user/changePassword"; + static final CHANGE_PASSWORD = "$baseUrl/customer/change-password"; + + static final FORGET_PASSWORD_STEP_1 = "$baseUrl/customer/forgetPassword/userid"; + static final FORGET_PASSWORD_STEP_2 = "$baseUrl/customer/forgetpassword"; + static final FORGET_PASSWORD_STEP_3 = "$baseUrl/customer/register/otp-resend"; + static final FORGET_PASSWORD_STEP_4 = "$baseUrl/customer/updatepassword"; + + static final SIGNUP_STEP_1 = "$baseUrl/security/auth/user/register"; + static final SIGNUP_STEP_2 = "$baseUrl/security/auth/verifysignup-otp"; + static final SIGNUP_STEP_3 = "$baseUrl/uco/auth/user/authenticate/onboardCustomer"; + static final SIGNUP_STEP_4 = "$baseUrl/customer/register/pin-verify"; + static final SIGNUP_STEP_4_RESEND_OTP = "$baseUrl/customer/register/pin-resend"; + static final SIGNUP_STEP_5 = "$baseUrl/customer/set-password"; + static final SEND_FEED_BACK = "$baseUrl/send-email"; + static final fetchPendingCredittransaction = "$baseUrl/uco/fetchPendingCredittransaction"; + static final ACCEPT_RECEIVE_TRANSACTION = "$baseUrl/uco/submitCrTransaction"; + static final REVERSE_TRANSACTION = "$baseUrl/uco/reverseTransaction"; + + static final FETCH_ACCOUNT_STATEMENT = "$baseUrl/uco/fetchDepositAccountStatement"; + static final FETCH_USER_ACTIVITY = "$baseUrl/uco/account/activity/"; + + static final fetchUcoDepositProducts = "$baseUrl/uco/auth/user/authenticate/onboardCustomer/fetchUcoDepositProducts"; + + static final FETCH_DEPOSIT_PRODUCTS = "$baseUrl/uco/deposit/fetchUcoDepositProducts"; + static final FETCH_GLS_ACCOUNTS = "$baseUrl/uco/deposit/fetchUcoGls"; + + static final SEND_ADD_MONEY_OTP = SEND_TRANSACTION_STEP1; + static final SEND_ADD_MONEY_TRANSACTION = "$baseUrl/uco/submitGLAccontAddMoneyTranasction"; + + static final evaluateCurrency = "$baseUrl/uco/getEvaluatedCurrency"; + static final ADD_NEW_ACCOUNT = "$baseUrl/uco/createUcoAccount"; + + + + static String resendOtp = "$baseUrl/security/auth/resend-otp"; + + + static String resendOtpUSend = "$baseUrl/uco/resendDrTranOtp"; + + static String resendTransOtp = "$baseUrl/uco/changeTransactionPin"; + static String createPinOtp = "$baseUrl/uco/createTransactionPin"; + static final ADD_NEW_BENEIFCIARY = "$baseUrl/uco/addBeneficary"; + static final DELETE_BENEFICIARY = "$baseUrl/uco/deleteBeneficary"; + static final FETCH_ALL_BENEFICIARY = "$baseUrl/uco/getBeneficary"; + +} \ No newline at end of file diff --git a/lib/app/core/constants/widget_types.dart b/lib/app/core/constants/widget_types.dart new file mode 100644 index 0000000..f1ea2c9 --- /dev/null +++ b/lib/app/core/constants/widget_types.dart @@ -0,0 +1,4 @@ +class WidgetTypes { + static const CUSTOM_EDIT_TEXT = "customEditText"; + static const CUSTOM_OTP_FIELD = "customOtpField"; +} diff --git a/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart b/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart new file mode 100644 index 0000000..18015cc --- /dev/null +++ b/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart @@ -0,0 +1,706 @@ + + +import '../../../../models/AddNewAccountRequestModel.dart'; +import '../../../../models/AuthenticationRequest.dart'; +import '../../../../models/BeneficiaryAccountModel.dart'; +import '../../../../models/ChangePasswordRequest.dart'; +import '../../../../models/ChangeTransactionPinRequest.dart'; +import '../../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../../models/CreateTransactionPinRequest.dart'; +import '../../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../../models/GenerateReportRequestModel.dart'; +import '../../../../models/RegisterRequest.dart'; +import '../../../../models/SignupOtpRequest.dart'; +import '../../../../models/SignupStep3RequestModel.dart'; +import '../../../../models/TransactionPinRequestModel.dart'; +import '../../../../models/TransactionSubmitRequestModel.dart'; +import '../../../../models/VerifyLoginOtpRequest.dart'; +import '../../../../models/accept_receive_transaction.dart'; +import '../../../../models/chanange_password_params.dart'; +import '../../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../../models/resend_ot_login_model.dart'; +import '../../../../models/resend_otp_usend.dart'; +import '../../../../models/upload_user_profile_model.dart'; +import '../../../config/requset_attr.dart'; +import '../../../config/server_request.dart'; +import '../../../config/server_response.dart'; +import '../../../constants/app_contants.dart'; +import '../../../constants/url_constants.dart'; +import '../../../enums/http_methods.dart'; +import '../../../utils/SessionCache.dart'; + +class AppRemoteDataSource { + Future fetchAccountDetails() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["pctCstycode"] = SessionCache.instance.userInfo.pctCstycode; + queryParams["cmpCustcode"] = SessionCache.instance.userInfo.cmpCustcode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_DETAILS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_DETAILS, HttpMethod.GET, {}, headers, queryParams)); + } + + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_ADD_MONEY_OTP, HttpMethod.POST, transactionPinRequestModel.toMap(), headers)); + } + + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_TRANSACTION_STEP1, HttpMethod.POST, transactionPinRequestModel.toMap(), headers)); + } + + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_TRANSACTION_STEP2, HttpMethod.POST, transactionSubmitRequestModel.toMap(), headers)); + } + + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_ADD_MONEY_TRANSACTION, HttpMethod.POST, transactionSubmitRequestModel.toMap(), headers)); + } + + Future getLoginOTP(AuthenticationRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GET_LOGIN_OTP; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN, HttpMethod.POST, requestModel.toMap())); + } + +// Future reSendOTP(ReSendOTPModel requestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN_OTP, HttpMethod.POST, requestModel.toJson())); +// } + + Future validateLoginPin(VerifyLoginOtpRequest requestBody) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.VALIDATE_LOGIN_PIN; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN_OTP, HttpMethod.POST, requestBody.toMap())); + } + + ///Fetch Account Transactions + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate) async { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + queryParams["sgtGntrvaluedatefrom"] = fromDate; + queryParams["sgtGntrvaluedateto"] = toDate; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_TRANSACTIONS, HttpMethod.GET, {}, headers, queryParams, {})); + } + + + Future addNewBeneficiary(BeneficiaryAccountModel beneficiaryModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.ADD_NEW_BENEFICIARY; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ADD_NEW_BENEIFCIARY, HttpMethod.POST, beneficiaryModel.toMap(), headers)); + } + + +// Future fetchLoanAccountDetails(String accountNumber) async { +// Map queryParams = {}; +// queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; +// queryParams["mbmBkmsnumber"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOAN_ACCOUNT_DETAILS, HttpMethod.GET, {}, headers, queryParams, {})); +// } + +// // http: //192.168.1.20:8080/MCONNECT/account/indvdetails?porOrgacode=0004&mbmBkmsnumber=0001325 + +// Future fetchLoanAccountTransactions(String accountNumber) async { +// Map queryParams = {}; +// queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; +// queryParams["mbmBkmsnumber"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOAN_ACCOUNT_TRANSACTIONS, HttpMethod.GET, {}, headers, queryParams, {})); +// } + + /// Fetch User Activity Data + Future fetchUserActivity(String fromDate, String toDate) async { + Map paramParameters = {}; + paramParameters["organization"] = SessionCache.instance.userInfo.porOrgacode; + paramParameters["customer"] = SessionCache.instance.userInfo.cmpCustcode; + // paramParameters["customertype"] = "I"; + paramParameters["fromdate"] = fromDate; + paramParameters["todate"] = toDate; + + // "uco/account/activity/organization/{porOrgacode}/customer/{cmpCustcode}/fromdate/{fdate}/todate/{tdate}"; + // /organization/0006/customer/I003120/fromdate/2024-01-01/todate/2024-04-29 + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = "Mobile"; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_USER_ACTIVITY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.FETCH_USER_ACTIVITY, paramParameters), HttpMethod.GET, {}, headers, {}, {})); + } + + + /// Method for handling Parameter + String buildPathParameters(String basePath, Map parameters) { + parameters.forEach((key, value) { + basePath += "/$key/$value"; + }); + return basePath; + } + + +// Future generatePinForBeneficiaryAccount(BeneficiaryPinRequestModel beneficiaryPinRequestModel) { +// Map paramParameters = {}; +// paramParameters["channel"] = SessionCache.instance.userInfo.channelCode; + +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.BENEFICIARY_PIN, paramParameters), HttpMethod.POST, beneficiaryPinRequestModel.toMap(), headers)); +// } + + Future fetchExchangeRate() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_EXCHANGE_RATE; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.EXCHANGE_RATE, HttpMethod.GET, {}, headers, queryParams)); + } + + Future fetchAccountInquiry(String type, String value) { + Map queryParams = {}; + queryParams["acntTypeCode"] = type; + queryParams["acntTypeValue"] = value; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["channelCode"] = SessionCache.instance.userInfo.channelCode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_IQUIRY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_INQUIRY, HttpMethod.GET, {}, headers, queryParams)); + } + + + + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CREATE_TRANSACTION_PIN; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CREATE_TRANSACTION_PIN_OTP, HttpMethod.POST, requestModel.toMap(), headers)); + } + + + Future createTransactionPin(CreateTransactionPinRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CREATE_TRANSACTION_PIN; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CREATE_TRANSACTION_PIN, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future changeTransactionPin(ChangeTransactionPinRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_TRANSACTION_PIN; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_TRANSACTION_PIN, HttpMethod.PUT, requestModel.toMap(), headers)); + } + + + Future generateReports(GenerateReportRequestModel requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GENERATE_REPORTS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.GENERATE_REPORTS, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future fetchGlsAllAccounts() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["glsTransaction"] = AppConstants.FETCH_GLS_ACCOUNTS; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_GLS_ACCOUNTS, HttpMethod.GET, {}, headers, queryParams)); + } + + Future uploadUserProfilePicture(UploadUserProfileModel uploadUserProfileModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.UPLOAD_USER_PROFILE_PICTURE; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.UPLOAD_USER_PROFILE_PICTURE, HttpMethod.POST, uploadUserProfileModel.toMap(), headers)); + } + +// Future deleteBeneficiary(String accountNumber) { +// Map paramParameters = {}; +// paramParameters["organization"] = SessionCache.instance.userInfo.porOrgacode; +// paramParameters["customer"] = SessionCache.instance.userInfo.cmpCustcode; +// paramParameters["customertype"] = "I"; +// paramParameters["account"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.DELETE_BENEFICIARYT, paramParameters), HttpMethod.DELETE, {}, headers, {}, {})); +// } + +// ------------------ Forget password ---------------- + +// Future forgetPasswordStep1(ForgetPasswordStep1RequestModel forgetPasswordStep1RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_1, HttpMethod.POST, forgetPasswordStep1RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep2(ForgetPasswordStep2RequestModel forgetPasswordStep2RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_2, HttpMethod.POST, forgetPasswordStep2RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep3(ForgetPasswordStep3RequestModel forgetPasswordStep3RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_3, HttpMethod.POST, forgetPasswordStep3RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep4(ForgetPasswordStep4RequestModel forgetPasswordStep4RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_4, HttpMethod.POST, forgetPasswordStep4RequestModel.toMap(), {})); +// } + +// sign up process + Future signupStep1(RegisterRequest registerRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGNUP_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_1, HttpMethod.POST, registerRequest.toMap(), {})); + } + + Future signupStep2(SignupOtpRequest signupOtpRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGUP_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_2, HttpMethod.POST, signupOtpRequest.toMap(), {})); + } + + + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGUP_STEP_3; + + var header = {'Content-Type': 'application/json'}; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_3, HttpMethod.POST, signupStep3RequestModel.toMap(), headers)); + } + + +// Future signupStep4(SignUpStep4RequestModel signUpStep4RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_4, HttpMethod.POST, signUpStep4RequestModel.toMap(), {})); +// } + +// Future signupStep4ResendOtp(SignUpStep4ResendOtpRequestModel signUpStep4ResendOtpRequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_4_RESEND_OTP, HttpMethod.POST, signUpStep4ResendOtpRequestModel.toMap(), {})); +// } + +// Future signupStep5(SignUpStep5RequestModel signUpStep5RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_5, HttpMethod.POST, signUpStep5RequestModel.toMap(), {})); +// } + + Future changePasswordSendOTP(ChangePasswordRequest changePasswordRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_PASSWORD_SEND_OTP; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_PASSWORD_SEND_OTP, HttpMethod.POST, changePasswordRequest.toMap(), headers)); + } + + Future changePassword(ChangePasswordParams changePasswordParams) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_PASSWORD; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_PASSWORD_SEND_OTP, HttpMethod.PATCH, changePasswordParams.toJson(), headers)); + } + + Future getPendingTransition(String accountNumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GET_PENDING_TRANSITION; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.fetchPendingCredittransaction, HttpMethod.GET, headers, queryParams)); + } + + + Future acceptReceiveTransition(AcceptReceiveTransactionModel requestModel) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.ACCEPT_RECEIVE_TRANSACTION; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCEPT_RECEIVE_TRANSACTION, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future reverseTransition(String nodeId, String sgtGntrnumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.REVERSE_TRANSACTION; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["nodeId"] = nodeId; + queryParams["sgtGntrnumber"] = sgtGntrnumber; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.REVERSE_TRANSACTION, HttpMethod.POST, {},headers, queryParams)); + } + + Future fetchAccountStatement(String accountNumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_STATEMENT; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.FETCH_ACCOUNT_STATEMENT, HttpMethod.GET, headers, queryParams)); + } + + Future getCurrencyList() { + Map queryParams = {}; + + queryParams["porOrgacode"] = "0005"; + + return ServerRequest.request( + RequestAttr.withHeaderAndParams(UrlContants.fetchUcoDepositProducts, HttpMethod.GET, {}, queryParams), + ); + } + + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_STATEMENT; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["baseCurrency"] = baseCurrency; + queryParams["targetCurrency"] = targetCurrency; + queryParams["sgtGntramtfc"] = sgtGntramtfc; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.evaluateCurrency, HttpMethod.GET, headers, queryParams)); + } + + Future addNewAccount(AddNewAccountRequestModel addNewAccountModel) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["addNewAccount"] = AppConstants.ADD_NEW_ACCOUNT; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ADD_NEW_ACCOUNT, HttpMethod.POST, addNewAccountModel.toMap(), headers)); + } + + Future resentOtpLoginSignUp(ResendOtpLoginModel model) { + Map headers = {}; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendOtp, HttpMethod.POST, model.toMap(), headers)); + } + + Future resendOtpUsend(ResendOtpUsendModel model) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendOtpUSend, HttpMethod.POST, model.toMap(), headers)); + } + + Future resendOtpTransPin( + ResendOtpChangeTransPin resendOtpChangeTransPin, + ) { + + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendTransOtp, HttpMethod.PUT, resendOtpChangeTransPin.toMap(), headers)); + } + + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody( + UrlContants.createPinOtp, + HttpMethod.PUT, + createTransactionPinRequest.toMap(), + headers, + )); + } + + Future fetchAllBeneficiary(String porOrgacode, String email) { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["email"] = SessionCache.instance.userInfo.cmpUserId; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ALL_BENEFICIARY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_ALL_BENEFICIARY, HttpMethod.GET, {}, headers, queryParams)); + } + + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) { + Map queryParams = {}; + queryParams["mbmBkmsnumberRef"] = mbmBkmsnumberRef; + queryParams["email"] = SessionCache.instance.userInfo.cmpUserId; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.DELETE_BENEFICIARY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.DELETE_BENEFICIARY, HttpMethod.DELETE, {}, headers, queryParams)); + } + +// Future loginResendOtp(LoginResendOtpRequestModel request) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.RESEND_OTP, HttpMethod.POST, request.toMap(), {})); +// } + +// Future fetchPaymentPurposes() { +// Map queryParams = {}; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_PAYMENT_PURPOSE, HttpMethod.GET, {}, headers, queryParams)); +// } + +// Future sendFeedBack(SendFeedBackRequestModel sendFeedBackRequestModel) { +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_FEED_BACK, HttpMethod.POST, sendFeedBackRequestModel.toMap(), headers)); +// } + +} diff --git a/lib/app/core/data/repositories/app_repositories.dart b/lib/app/core/data/repositories/app_repositories.dart new file mode 100644 index 0000000..70015f4 --- /dev/null +++ b/lib/app/core/data/repositories/app_repositories.dart @@ -0,0 +1,271 @@ + + +import '../../../models/AddNewAccountRequestModel.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/ChangeTransactionPinRequest.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../models/CreateTransactionPinRequest.dart'; +import '../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../models/RegisterRequest.dart'; +import '../../../models/SignupOtpRequest.dart'; +import '../../../models/SignupStep3RequestModel.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/VerifyLoginOtpRequest.dart'; +import '../../../models/accept_receive_transaction.dart'; +import '../../../models/chanange_password_params.dart'; +import '../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../models/resend_ot_login_model.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../models/upload_user_profile_model.dart'; +import '../../config/server_response.dart'; +import '../data_source_auth/remote_data_source/app_remote_data_source.dart'; + +abstract class AppRepositories { + Future login(AuthenticationRequest request); + + Future validateLoginPin(VerifyLoginOtpRequest request); + + Future fetchAccountDetails(); + + Future fetchGlsAccounts(); + + Future fetchAccountInquiry(String type, String value); + + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate); + + Future fetchExchangeRate(); + + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel); + + Future createTransactionPin(CreateTransactionPinRequest requestModel); + + Future uploadUserProfilePicture(UploadUserProfileModel requestModel); + + Future changeTransactionPin(ChangeTransactionPinRequest requestModel); + + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel); + + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel); + + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel); + + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel); + + Future acceptReceiveTransaction(AcceptReceiveTransactionModel requestModel); + + Future reverseTransaction(String nodeId, String sgtGntrnumber); + + Future addNewBeneficiary(BeneficiaryAccountModel requestModel); + + Future fetchAllBeneficiary(String porOrgacode, String email); + + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode); + + Future signupStep1(RegisterRequest registerRequest); + + Future signupStep2(SignupOtpRequest signupOtpRequest); + + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel); + + Future changePassword(ChangePasswordParams changePasswordParams); + + Future getPendingTransition(String accountNumber); + + Future fetchAccountStatement(String accountNumber); + + Future fetchUserActivity(String fromDate, String toDate); + + Future resentOtpLoginSignUp(ResendOtpLoginModel model); + + Future getCurrencyList(); + + Future addNewAccount(AddNewAccountRequestModel addNewAccountRequest); + + Future resendOtpUsend(ResendOtpUsendModel resendOtpUsendModel); + + Future resendOtpTransPin(ResendOtpChangeTransPin resendOtpChangeTransPin); + + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest); + + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc); +} + +class AppRepositoriesImpl implements AppRepositories { + AppRemoteDataSource remoteDataSource; + + AppRepositoriesImpl({required this.remoteDataSource}); + + @override + Future login(AuthenticationRequest requestModel) { + return remoteDataSource.getLoginOTP(requestModel); + } + + @override + Future fetchAccountDetails() { + return remoteDataSource.fetchAccountDetails(); + } + + @override + Future fetchAccountInquiry(String type, String value) { + return remoteDataSource.fetchAccountInquiry(type, value); + } + + /// + @override + Future validateLoginPin(VerifyLoginOtpRequest requestModel) { + return remoteDataSource.validateLoginPin(requestModel); + } + + @override + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate) { + return remoteDataSource.fetchDepositAccountTransactions(accountNumber, fromDate, toDate); + } + + @override + Future fetchExchangeRate() { + return remoteDataSource.fetchExchangeRate(); + } + + @override + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel) { + return remoteDataSource.sendTransactionStep1(transactionPinRequestModel); + } + + // + @override + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel) { + return remoteDataSource.sendTransactionStep2(transactionSubmitRequestModel); + } + + @override + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel) { + return remoteDataSource.sendAddMoneyOtp(transactionPinRequestModel); + } + + @override + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel) { + return remoteDataSource.sendAddMoneyTransaction(transactionSubmitRequestModel); + } + + @override + Future signupStep1(RegisterRequest registerRequest) { + return remoteDataSource.signupStep1(registerRequest); + } + + @override + Future signupStep2(SignupOtpRequest signupOtpRequest) { + return remoteDataSource.signupStep2(signupOtpRequest); + } + + @override + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel) { + return remoteDataSource.signupStep3(signupStep3RequestModel); + } + + @override + Future changePassword(ChangePasswordParams changePasswordParams) { + return remoteDataSource.changePassword(changePasswordParams); + } + + @override + Future getPendingTransition(String accountNumber) { + return remoteDataSource.getPendingTransition(accountNumber); + } + + @override + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel) { + return remoteDataSource.createTransactionPinOTP(requestModel); + } + + @override + Future createTransactionPin(CreateTransactionPinRequest requestModel) { + return remoteDataSource.createTransactionPin(requestModel); + } + + @override + Future changeTransactionPin(ChangeTransactionPinRequest requestModel) { + return remoteDataSource.changeTransactionPin(requestModel); + } + + @override + Future acceptReceiveTransaction(AcceptReceiveTransactionModel requestModel) { + return remoteDataSource.acceptReceiveTransition(requestModel); + } + + @override + Future fetchAccountStatement(String accountNumber) { + return remoteDataSource.fetchAccountStatement(accountNumber); + } + + @override + Future fetchUserActivity(String fromDate, String toDate) { + return remoteDataSource.fetchUserActivity(fromDate, toDate); + } + + @override + Future getCurrencyList() { + return remoteDataSource.getCurrencyList(); + } + + @override + Future fetchGlsAccounts() { + return remoteDataSource.fetchGlsAllAccounts(); + } + + @override + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc) { + return remoteDataSource.getConvertedCurrency(baseCurrency, targetCurrency, sgtGntramtfc); + } + + @override + Future addNewAccount(AddNewAccountRequestModel addNewAccountRequest) { + return remoteDataSource.addNewAccount(addNewAccountRequest); + } + + @override + Future resentOtpLoginSignUp(ResendOtpLoginModel model) { + return remoteDataSource.resentOtpLoginSignUp(model); + } + + @override + Future resendOtpUsend(ResendOtpUsendModel resendOtpUsendModel) { + return remoteDataSource.resendOtpUsend(resendOtpUsendModel); + } + + @override + Future resendOtpTransPin(ResendOtpChangeTransPin resendOtpChangeTransPin) { + return remoteDataSource.resendOtpTransPin(resendOtpChangeTransPin); + } + + @override + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest) { + return remoteDataSource.createPinResndOtp(createTransactionPinRequest); + } + + @override + Future uploadUserProfilePicture(UploadUserProfileModel requestModel) { + return remoteDataSource.uploadUserProfilePicture(requestModel); + } + + @override + Future reverseTransaction(String nodeId, String sgtGntrnumber) { + return remoteDataSource.reverseTransition(nodeId, sgtGntrnumber); + } + + @override + Future addNewBeneficiary(BeneficiaryAccountModel requestModel) { + return remoteDataSource.addNewBeneficiary(requestModel); + } + + @override + Future fetchAllBeneficiary(String porOrgacode, String email) { + return remoteDataSource.fetchAllBeneficiary(porOrgacode, email); + } + + @override + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) { + return remoteDataSource.deleteBeneficiary(mbmBkmsnumberRef, email, porOrgacode); + } +} diff --git a/lib/app/core/dialogs/custom_loading.dart b/lib/app/core/dialogs/custom_loading.dart new file mode 100644 index 0000000..448a580 --- /dev/null +++ b/lib/app/core/dialogs/custom_loading.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:loader_overlay/loader_overlay.dart'; + +import '../../res/app_colors.dart'; +import '../constants/app_assets.dart'; + + +class CustomLoading extends StatefulWidget { + const CustomLoading({Key? key, this.type = 0}) : super(key: key); + + final int type; + + @override + _CustomLoadingState createState() => _CustomLoadingState(); +} + +class _CustomLoadingState extends State with TickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + _controller = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + _controller.forward(); + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + _controller.reset(); + _controller.forward(); + } + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Visibility(visible: widget.type == 2, child: _buildLoadingTwo()); + } + + // Widget _buildLoadingOne() { + // return Stack(alignment: Alignment.center, children: [ + // RotationTransition( + // alignment: Alignment.center, + // turns: _controller, + // child: Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101174606.png', + // height: 110, + // width: 110, + // ), + // ), + // Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101181404.png', + // height: 60, + // width: 60, + // ), + // ]); + // } + + Widget _buildLoadingTwo() { + return Container( + padding: const EdgeInsets.all(30.0), + decoration: BoxDecoration( + color: AppColors.white, + border: Border.all(color: Colors.white), + borderRadius: BorderRadius.circular(20.0), + ), + child: RotationTransition( + alignment: Alignment.center, + turns: _controller, + child: Image( + image: const AssetImage(AppAssets.kprogresshud_spinner), + color: Colors.black.withOpacity(0.5), + height: 50, + width: 50, + ), + ), + ); + } + + // Widget _buildLoadingThree() { + // return Center( + // child: Container( + // height: 120, + // width: 180, + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(15), + // ), + // alignment: Alignment.center, + // child: Column(mainAxisSize: MainAxisSize.min, children: [ + // RotationTransition( + // alignment: Alignment.center, + // turns: _controller, + // child: Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101163010.png', + // height: 50, + // width: 50, + // ), + // ), + // Container( + // margin: EdgeInsets.only(top: 20), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLoading)), + // ), + // ]), + // ), + // ); + // } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } +} + +showLoader() { + // Get.context!.loaderOverlay.show( + // widgetBuilder: (progress) => const Center( + // child: CustomLoading( + // type: 2, + // ), + // ), + // ); + + Get.context!.loaderOverlay.show( + widgetBuilder: (progress) => const Center( + child: Card( + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: 15, + // ), + // const CupertinoActivityIndicator( + // radius: 25, + // ), + CustomLoading(type: 2), + //SizedBox(height: 15), + // Text( + // "Loading", + // style: Theme.of(Get.context!).textTheme.bodyMedium, + // ), + // const SizedBox( + // height: 15, + // ), + ], + ), + ), + ), + ), + ); +} + +hideLoader() { + Get.context!.loaderOverlay.hide(); +} diff --git a/lib/app/core/enums/api_keys.dart b/lib/app/core/enums/api_keys.dart new file mode 100644 index 0000000..e6e3e91 --- /dev/null +++ b/lib/app/core/enums/api_keys.dart @@ -0,0 +1,66 @@ +/* +enum ApiKeys { + cmpUserId, + cmpCustpassword, + channelCode, + porOrgacode, + pctCstycode, + cmpIdennumber, + cmpUserIdType, + arguments, + cmpAccountno, + cmpCustcode, + phoneNo, + obpPincode, + newCustpassword +} + +extension ApiKeysExtension on ApiKeys { + String get value { + switch (this) { + case ApiKeys.cmpUserId: + return 'cmpUserId'; + case ApiKeys.cmpCustpassword: + return 'cmpCustpassword'; + case ApiKeys.channelCode: + return 'channelCode'; + case ApiKeys.porOrgacode: + return 'porOrgacode'; + case ApiKeys.pctCstycode: + return 'pctCstycode'; + case ApiKeys.cmpIdennumber: + return 'cmpIdennumber'; + case ApiKeys.cmpUserIdType: + return 'cmpUserIdType'; + case ApiKeys.arguments: + return 'arguments'; + case ApiKeys.cmpAccountno: + return 'cmpAccountno'; + case ApiKeys.cmpCustcode: + return 'cmpCustcode'; + case ApiKeys.phoneNo: + return 'phoneNo'; + case ApiKeys.obpPincode: + return 'obpPincode'; + case ApiKeys.newCustpassword: + return 'newCustpassword'; + } + } +} +*/ + +// class ApiKeys { +// static const String cmpUserId = 'cmpUserId'; +// static const String cmpCustpassword = 'cmpCustpassword'; +// static const String channelCode = 'channelCode'; +// static const String porOrgacode = 'porOrgacode'; +// static const String pctCstycode = 'pctCstycode'; +// static const String cmpIdennumber = 'cmpIdennumber'; +// static const String cmpUserIdType = 'cmpUserIdType'; +// static const String arguments = 'arguments'; +// static const String cmpAccountno = 'cmpAccountno'; +// static const String cmpCustcode = 'cmpCustcode'; +// static const String phoneNo = 'phoneNo'; +// static const String obpPincode = 'obpPincode'; +// static const String newCustpassword = 'newCustpassword'; +// } diff --git a/lib/app/core/enums/countryCode.dart b/lib/app/core/enums/countryCode.dart new file mode 100644 index 0000000..d7158de --- /dev/null +++ b/lib/app/core/enums/countryCode.dart @@ -0,0 +1,7 @@ +enum CountryCode { US, SA } + +extension CountryCodeExtension on CountryCode { + String get getKey { + return ["US", "SA"][index]; + } +} diff --git a/lib/app/core/enums/http_methods.dart b/lib/app/core/enums/http_methods.dart new file mode 100644 index 0000000..9225320 --- /dev/null +++ b/lib/app/core/enums/http_methods.dart @@ -0,0 +1 @@ +enum HttpMethod { GET, POST, PUT, DELETE,PATCH } diff --git a/lib/app/core/enums/languageCode.dart b/lib/app/core/enums/languageCode.dart new file mode 100644 index 0000000..f6fddc6 --- /dev/null +++ b/lib/app/core/enums/languageCode.dart @@ -0,0 +1,7 @@ +enum LanguageCode { ENGLISH, ARABIC } + +extension LanguageCodeExtension on LanguageCode { + String get getKey { + return ["en", "ar"][index]; + } +} diff --git a/lib/app/core/enums/request_constants.dart b/lib/app/core/enums/request_constants.dart new file mode 100644 index 0000000..8244737 --- /dev/null +++ b/lib/app/core/enums/request_constants.dart @@ -0,0 +1,8 @@ +class RequestConstants { + // static const String porOrgacode = "0004"; // Genish + static const String porOrgacode = "0005"; // BEMO + static const String pctCstycode = "I"; + static const String channelCode = "01"; + static const String plcLocacode = "plcLocacode"; + static const bool isOTPRequired = true; +} diff --git a/lib/app/core/enums/screen_type.dart b/lib/app/core/enums/screen_type.dart new file mode 100644 index 0000000..7405884 --- /dev/null +++ b/lib/app/core/enums/screen_type.dart @@ -0,0 +1 @@ +enum FieldTypes { multiLevelFields, otpField, multipleField } diff --git a/lib/app/core/extensions/build_context_ext.dart b/lib/app/core/extensions/build_context_ext.dart new file mode 100644 index 0000000..ac04d82 --- /dev/null +++ b/lib/app/core/extensions/build_context_ext.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../utils/logs_utils.dart'; + +extension BuildContextExt on BuildContext? { + // + + showSnakBar({required String msg}) { + if (msg.isEmpty) { + dp("Mess age is empty", msg); + return; + } + ScaffoldMessenger.of(this!).showSnackBar(SnackBar( + content: Text( + msg, + style: Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + backgroundColor: Colors.white, + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + duration: const Duration(seconds: 4), + )); + } + + showGeneralDialog(List? children, {bool isShowOverly = false, bool dissmiss = true}) { + showDialog( + context: this!, + barrierDismissible: dissmiss, + barrierColor: isShowOverly ? Get.context.themeData.colorScheme.secondary.withOpacity(0.4) : null, + builder: (context) { + return SimpleDialog( + alignment: Alignment.center, + backgroundColor: Get.context.themeData.colorScheme.secondary, + children: children, + ); + }, + ); + } + + Size get getSize => MediaQuery.of(this!).size; + + double get getHeight => MediaQuery.of(this!).size.height; + + double get getWidth => MediaQuery.of(this!).size.width; + + TextTheme get textTheme => Theme.of(this!).textTheme; + + ThemeData get themeData => Theme.of(this!); + + bool get isSmall => MediaQuery.of(this!).size.height <= 690; + + bool get isVSmall => MediaQuery.of(this!).size.height <= 550; + + bool get isMedium => MediaQuery.of(this!).size.height < 750; +} diff --git a/lib/app/core/local_stoarge/app_storage.dart b/lib/app/core/local_stoarge/app_storage.dart new file mode 100644 index 0000000..67d1bbb --- /dev/null +++ b/lib/app/core/local_stoarge/app_storage.dart @@ -0,0 +1,169 @@ +import 'dart:convert'; +import 'package:hive/hive.dart'; + +class AppStorage { + // static const _storage = FlutterSecureStorage(); + // static Future> getAllData() async { + // final allData = await _storage.readAll(); + // return allData; + // } + // // Put methods + // static Future putString(String key, String value) async { + // await _storage.write(key: key, value: value); + // } + // + // static Future putInt(String key, int value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putDouble(String key, double value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putBoolean(String key, bool value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putObject(String key, Object value) async { + // final jsonString = jsonEncode(value); + // await _storage.write(key: key, value: jsonString); + // } + // + // static Future putList(String key, List value) async { + // final jsonString = jsonEncode(value); + // await _storage.write(key: key, value: jsonString); + // } + // + // // Get methods with optional fallbacks + // static Future getString(String key, {String fallback = ''}) async { + // final value = await _storage.read(key: key); + // return value ?? fallback; + // } + // + // static Future getInt(String key, {int fallback = 0}) async { + // final value = await _storage.read(key: key); + // return value != null ? int.parse(value) : fallback; + // } + // + // static Future getDouble(String key, {double fallback = 0.0}) async { + // final value = await _storage.read(key: key); + // return value != null ? double.parse(value) : fallback; + // } + // + // static Future getBoolean(String key, {bool fallback = false}) async { + // final value = await _storage.read(key: key); + // return value != null && value.toLowerCase() == 'true' ? true : fallback; + // } + // + // static Future getObject(String key, {Object fallback = const {}}) async { + // final value = await _storage.read(key: key); + // return value != null ? jsonDecode(value) : fallback; + // } + // + // static Future> getList(String key, {List fallback = const []}) async { + // final value = await _storage.read(key: key); + // return value != null ? List.from(jsonDecode(value)) : fallback; + // } + +// Delete method (same as before) + + static Future putString(String key, String value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future delete(String key) async { + final box = await Hive.openBox('appBox'); + await box.delete(key); + await box.close(); + } + + static Future putInt(String key, int value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putDouble(String key, double value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putBoolean(String key, bool value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putObject(String key, Object value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, jsonEncode(value)); + await box.close(); + } + + static Future putList(String key, List value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, jsonEncode(value)); + await box.close(); + } + + static Future getString(String key, {String fallback = ''}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getInt(String key, {int fallback = 0}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getDouble(String key, {double fallback = 0.0}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getBoolean(String key, {bool fallback = false}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getObject(String key, + {Object fallback = const {}}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value != null ? jsonDecode(value) : fallback; + } + + static Future> getList(String key, + {List fallback = const []}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value != null ? List.from(jsonDecode(value)) : fallback; + } + + static Future> getAllData() async { + final box = await Hive.openBox('appBox'); + final keys = box.keys.toList(); + final List allData = []; + + for (final key in keys) { + final value = box.get(key); + allData.add({'key': key, 'value': value}); + } + + await box.close(); + return allData; + } +} diff --git a/lib/app/core/utils/FingerPrintController.dart b/lib/app/core/utils/FingerPrintController.dart new file mode 100644 index 0000000..bf3f6ab --- /dev/null +++ b/lib/app/core/utils/FingerPrintController.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; + +import '../../models/finger_print_info.dart'; +import '../constants/app_contants.dart'; +import '../local_stoarge/app_storage.dart'; +import 'SessionCache.dart'; +// import 'package:local_auth/local_auth.dart'; + + +class FingerPrintController { + LocalAuthentication _localAuth = LocalAuthentication(); + RxBool isFingerPrintExistInDB = false.obs; + RxBool isFingerprintSupported = false.obs; + + FingerPrintController() { + _localAuth = LocalAuthentication(); + checkFingerprintSupport(); + checkIfExistDB(); + } + + Future checkIfExistDB() async { + String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + isFingerPrintExistInDB.value = info.isNotEmpty; + } + + Future authenticate(Function(bool status)? callback, bool saveToDB) async { + try { + bool authenticated = await _localAuth.authenticate( + localizedReason: 'Authenticate to access the app', + options: const AuthenticationOptions( + stickyAuth: true, + biometricOnly: true, + useErrorDialogs: true, + ), + ); + if (authenticated) { + if (saveToDB) { + FingerPrintInfo fingerPrintInfo = FingerPrintInfo(); + fingerPrintInfo.porOrgacode = SessionCache.instance.userInfo.porOrgacode; + fingerPrintInfo.channelCode = SessionCache.instance.userInfo.channelCode; + fingerPrintInfo.cmpUserId = SessionCache.instance.userInfo.cmpUserId; + fingerPrintInfo.cmpCustpassword = SessionCache.instance.userInfo.cmpCustpassword; + await AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, jsonEncode(fingerPrintInfo.toMap())); + isFingerPrintExistInDB.value = true; + isFingerprintSupported.value = true; + } + if (callback != null) { + callback(true); + } + } else { + if (callback != null) { + callback(false); + } + } + } catch (e) { + print(e); + } + } + + Future checkFingerprintSupport() async { + isFingerprintSupported.value = await _localAuth.isDeviceSupported(); + } + + Future clearFromDB() async { + await AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + isFingerPrintExistInDB.value = false; + } +} diff --git a/lib/app/core/utils/SessionCache.dart b/lib/app/core/utils/SessionCache.dart new file mode 100644 index 0000000..9aa8de3 --- /dev/null +++ b/lib/app/core/utils/SessionCache.dart @@ -0,0 +1,79 @@ +import 'package:get/get.dart'; +import '../../models/DepositAccountResponse.dart'; +import '../../models/ExchangeRate.dart'; +import '../../models/GlsResponseModel.dart'; +import '../../models/UserInfo.dart'; +import 'FingerPrintController.dart'; + +class SessionCache { + static final SessionCache _instance = SessionCache._internal(); + + factory SessionCache() { + return _instance; + } + + SessionCache._internal(); + + FingerPrintController _fingerPrintController = FingerPrintController(); + + UserInfo userInfo = UserInfo(); + + RxList _depositAccountList = RxList.empty(); + + RxList _exchangeRateList = RxList.empty(); + RxList _glsAccountsList = RxList.empty(); + + // RxList _paymentPurposeList = RxList.empty(); + // RxList _loanAccountList = RxList.empty(); + // List _beneficiaryAccountList = []; + // List _favBeneficiaryAccountList = []; + + static SessionCache get instance => _instance; + + RxList get exchangeRateList => _exchangeRateList; + + RxList get glsAccountsList => _glsAccountsList; + + set glsAccountsList(RxList value) { + _glsAccountsList = value; + } + + set exchangeRateList(RxList value) { + _exchangeRateList = value; + } //RxList get paymentPurposeList => _paymentPurposeList; + + // set paymentPurposeList(RxList value) { + // _paymentPurposeList = value; + // } + + RxList get depositAccountList => _depositAccountList; + + // List get favBeneficiaryAccountList => _favBeneficiaryAccountList; + // + FingerPrintController get fingerPrintController => _fingerPrintController; + + // + // RxList get loanAccountList => _loanAccountList; + // + // List get beneficiaryAccountList => _beneficiaryAccountList; + // + // set favBeneficiaryAccountList(List value) { + // _favBeneficiaryAccountList = value; + // } + // + // set fingerPrintController(FingerPrintController value) { + // _fingerPrintController = value; + // } + + setDepositAccountList(RxList value) { + _depositAccountList = value; + } + +// set loanAccountList(RxList value) { +// _loanAccountList = value; +// } +// +// set beneficiaryAccountList(List value) { +// _beneficiaryAccountList = value; +// } +} diff --git a/lib/app/core/utils/app_utils.dart b/lib/app/core/utils/app_utils.dart new file mode 100644 index 0000000..e4cf4b5 --- /dev/null +++ b/lib/app/core/utils/app_utils.dart @@ -0,0 +1,93 @@ +import 'package:intl/intl.dart'; + +import '../../models/ExchangeRate.dart'; +import 'SessionCache.dart'; + + +class AppUtils { + /// Balance show format method + static String formatCurrency(num value) { + final currencyFormatter = NumberFormat.currency( + // locale: 'eu', + customPattern: '#,##,###', + symbol: '', // Set the currency symbol + decimalDigits: 2, // Set the number of decimal places + ); + + return currencyFormatter.format(value); + } + + bool isValidEmail(String email) { + final RegExp emailRegex = RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$'); + return emailRegex.hasMatch(email); + } + + static String formatDateTime(String dateTimeString, String format) { + DateTime dateTime = DateTime.parse(dateTimeString); + final formatter = DateFormat(format); + String formattedDateTime = formatter.format(dateTime); + return formattedDateTime; + } + + static String showAmountWithCurr(String amount, String currencyCode) { + ExchangeRate exchangeRate = SessionCache.instance.exchangeRateList.firstWhere((rate) => rate.pcrCurrcode == currencyCode, orElse: () => ExchangeRate.empty()); + return exchangeRate.pcrCurrshort.isEmpty ? '$currencyCode $amount' : '${exchangeRate.pcrCurrshort} $amount'; + } + + static String accountNumberFormatter(String accountNumber) { + return accountNumber; + } + + static bool isPasswordValid(String password, [int minLength = 8]) { + bool hasUppercase = password.contains(RegExp(r'[A-Z]')); + bool hasDigits = password.contains(RegExp(r'[0-9]')); + bool hasLowercase = password.contains(RegExp(r'[a-z]')); + bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); + bool hasMinLength = password.length >= minLength; + return hasDigits & hasUppercase & hasLowercase & hasSpecialCharacters & hasMinLength; + } + + static String getInitials(String fullName) { + List words = fullName.split(' '); + if (words.isNotEmpty) { + String initials = words.map((word) => word.isNotEmpty ? word[0].toUpperCase() : '').join(); + return initials.length >= 2 ? initials.substring(0, 2) : initials; + } else { + return ''; + } + } + + static String formatPhoneNumber(String phoneNumber) { + if (phoneNumber.startsWith("0")) { + phoneNumber = "+92${phoneNumber.substring(1)}"; + } + if (phoneNumber.startsWith("3")) { + phoneNumber = "+92$phoneNumber"; + } + if (phoneNumber.startsWith("92")) { + phoneNumber = "+$phoneNumber"; + } + if (phoneNumber.contains("-")) { + phoneNumber = phoneNumber.replaceAll("-", ""); + } + phoneNumber = phoneNumber.replaceAll(" ", ""); + return phoneNumber; + } + + static String convertDateTime(String timestamp) { + // Parse the timestamp string into a DateTime object + DateTime dateTime = DateTime.parse(timestamp); + + // Format the DateTime object to display only the date and time + String formattedDateTime = + '${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} ' + '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}:${dateTime.second.toString().padLeft(2, '0')}'; + + return formattedDateTime; + } + + + static String showAmountWithCurrencyCode(String amount) { + return "Rs. " + amount; + } +} diff --git a/lib/app/core/utils/fields_utils.dart b/lib/app/core/utils/fields_utils.dart new file mode 100644 index 0000000..70a0bc3 --- /dev/null +++ b/lib/app/core/utils/fields_utils.dart @@ -0,0 +1,12 @@ +import 'package:flutter/services.dart'; + +class FieldUtils { + static const int userNameFieldLength = 100; + static const int transactionPinLength = 6; + static const int addressFieldLength = 250; + static const int phoneNumberFieldLength = 100; +} + +hideKeyBoard() { + SystemChannels.textInput.invokeMethod('TextInput.hide'); +} diff --git a/lib/app/core/utils/globle_keys.dart b/lib/app/core/utils/globle_keys.dart new file mode 100644 index 0000000..a47f241 --- /dev/null +++ b/lib/app/core/utils/globle_keys.dart @@ -0,0 +1 @@ +import 'package:flutter/material.dart'; diff --git a/lib/app/core/utils/logs_utils.dart b/lib/app/core/utils/logs_utils.dart new file mode 100644 index 0000000..c55117e --- /dev/null +++ b/lib/app/core/utils/logs_utils.dart @@ -0,0 +1,23 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; + +dp(msg, arg) { + // debugPrint("\n"); + + if (Platform.isAndroid) { + debugPrint("\u001b[1;32m $msg $arg"); + } else { + debugPrint("$msg $arg"); + } +} + +pe(msg, arg) { + if (Platform.isAndroid) { + debugPrint("\u001b[1;31m $msg "); + debugPrint("\u001b[1;31m $arg"); + } else { + debugPrint("$msg "); + debugPrint("$arg"); + } +} diff --git a/lib/app/core/utils/phone_number_utils.dart b/lib/app/core/utils/phone_number_utils.dart new file mode 100644 index 0000000..8e26ff6 --- /dev/null +++ b/lib/app/core/utils/phone_number_utils.dart @@ -0,0 +1,9 @@ +class PhoneNumberUtils { + static String phoneCodeText = '(+92) '; + static String phoneCode = '+92'; + + static int getPhoneNumberLength() { + return 12; + } + +} diff --git a/lib/app/core/utils/root_detector_device.dart b/lib/app/core/utils/root_detector_device.dart new file mode 100644 index 0000000..c311a4c --- /dev/null +++ b/lib/app/core/utils/root_detector_device.dart @@ -0,0 +1,45 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:root_checker_plus/root_checker_plus.dart'; + +Future isDeviceRootedOrJailbroken() async { + if (Platform.isAndroid) { + bool? isRooted = await RootCheckerPlus.isRootChecker(); + return isRooted ?? false; + } else if (Platform.isIOS) { + return await _isJailbroken(); + } else { + return false; // Other platforms are not supported + } +} + +Future _isJailbroken() async { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + + // List of common jailbreak indicators + List jailbreakIndicators = ['/Applications/Cydia.app', '/Library/MobileSubstrate/MobileSubstrate.dylib', '/bin/bash', '/usr/sbin/sshd', '/etc/apt', '/private/var/lib/apt/', '/private/var/lib/cydia', '/var/log/syslog']; + + // Check for the existence of jailbreak indicator files + for (String indicator in jailbreakIndicators) { + if (File(indicator).existsSync()) { + return true; + } + } + + // Check if we can write outside the app's sandbox + try { + File('/private/jailbreak.txt').writeAsStringSync('Jailbreak test'); + return true; + } catch (e) { + // If we cannot write outside the sandbox, it's likely not jailbroken + } + + // Check for suspicious environment variables + if (Platform.environment.containsKey('DYLD_INSERT_LIBRARIES')) { + return true; + } + + return false; +} diff --git a/lib/app/core/utils/simulator_check.dart b/lib/app/core/utils/simulator_check.dart new file mode 100644 index 0000000..6e3392b --- /dev/null +++ b/lib/app/core/utils/simulator_check.dart @@ -0,0 +1,17 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; + +Future isEmulator() async { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + return !androidInfo.isPhysicalDevice; + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + return !iosInfo.isPhysicalDevice; + } else { + return false; + } +} diff --git a/lib/app/core/utils/url_encryption.dart b/lib/app/core/utils/url_encryption.dart new file mode 100644 index 0000000..0a02eb1 --- /dev/null +++ b/lib/app/core/utils/url_encryption.dart @@ -0,0 +1,59 @@ +import 'package:encrypt/encrypt.dart' as encrypt; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +// class UrlEncryption { +// /// The singleton instance +// static final UrlEncryption _instance = UrlEncryption._internal(); +// +// /// Private constructor +// // UrlEncryption._internal() { +// // _init(); +// // } +// +// /// Factory constructor to return the same instance +// factory UrlEncryption() { +// return _instance; +// } +// +// /// Encryption key +// encrypt.Key? _key; +// +// /// Method to initialize the encryption key from environment variable +// // void _init() { +// // final keyString = dotenv.env['ENCRYPTION_KEY']; +// // if (keyString == null || keyString.length != 32) { +// // throw Exception('Invalid encryption key in environment variables.'); +// // } +// // _key = encrypt.Key.fromUtf8(keyString); +// // } +// +// /// Method to encrypt data +// String encryptData(String data) { +// if (_key == null) { +// throw Exception('Encryption key is not initialized.'); +// } +// final iv = encrypt.IV.fromLength(16); // Generate a random IV +// final encrypter = encrypt.Encrypter(encrypt.AES(_key!, mode: encrypt.AESMode.cbc)); +// +// final encrypted = encrypter.encrypt(data, iv: iv); +// final ivBase64 = iv.base64; +// final encryptedBase64 = encrypted.base64; +// +// return '$ivBase64:$encryptedBase64'; // Store IV and ciphertext together +// } +// +// /// Method to decrypt data +// String decryptData(String encryptedData) { +// if (_key == null) { +// throw Exception('Encryption key is not initialized.'); +// } +// final parts = encryptedData.split(':'); +// final iv = encrypt.IV.fromBase64(parts[0]); // Extract the IV +// final encrypted = encrypt.Encrypted.fromBase64(parts[1]); +// +// final encrypter = encrypt.Encrypter(encrypt.AES(_key!, mode: encrypt.AESMode.cbc)); +// final decrypted = encrypter.decrypt(encrypted, iv: iv); +// +// return decrypted; +// } +// } diff --git a/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart b/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart new file mode 100644 index 0000000..62bb384 --- /dev/null +++ b/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart @@ -0,0 +1,267 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../core/constants/translation_keys.dart'; +import '../../res/app_colors.dart'; +import '../custom_dropdown.dart'; +import '../custom_text.dart'; +import 'input_field.dart'; + +class CustomDropDownBottomSheet { + void showBottomSheet(BuildContext context, List options, + String type, Function(DropDown)? onItemSelected) { + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey500, width: 1), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, type, (selectedOption) { + if (onItemSelected != null) { + onItemSelected(selectedOption); + } + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +@immutable +class DialogDesign extends StatelessWidget { + List options = []; + String type = ""; + Function(DropDown) onSelect; + + DialogDesign(this.options, this.type, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: type == DropDownType.NORMAL, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: AppColors.colorGrey700, + fontSize: 16, + fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); + }, + child: CircleAvatar( + radius: 15, + backgroundColor: Colors.transparent, + child: Icon(Icons.close, + size: 20.0, color: Colors.blue)), + ), + ], + ), + SizedBox(height: 10.0), + ], + )), + FilterableBottomSheet( + options: options, type: type, onSelect: onSelect), + ], + ), + ); + } +} + +class FilterableBottomSheet extends StatefulWidget { + final List options; + final String type; + final Function(DropDown) onSelect; + + FilterableBottomSheet( + {required this.options, required this.onSelect, required this.type}); + + @override + _FilterableBottomSheetState createState() => _FilterableBottomSheetState(); +} + +class _FilterableBottomSheetState extends State { + TextEditingController _filterTextController = TextEditingController(); + List _filteredOptions = []; + + @override + void initState() { + super.initState(); + _filteredOptions.addAll(widget.options); + } + + void _updateFilteredList(String query) { + setState(() { + _filteredOptions.clear(); + if (query.isEmpty) { + _filteredOptions.addAll(widget.options); + } else { + query = query.toLowerCase(); + _filteredOptions.addAll(widget.options + .where((item) => item.label.toLowerCase().contains(query))); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: widget.type == DropDownType.NORMAL, + child: Column( + children: [ + Container( + height: 40, + padding: EdgeInsets.symmetric(horizontal: 15.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(Icons.search, + size: 20, color: AppColors.colorGrey700), + SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w500, fontSize: 14), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textSearch), + ), + controller: _filterTextController, + onChanged: _updateFilteredList, + ), + ), + ], + ), + ), + SizedBox(height: 20.0), + ], + ), + ), + Container( + height: _filteredOptions.length <= 5 + ? (45 * _filteredOptions.length) + + (10 * (_filteredOptions.length - 1)) + : 300, + child: ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + itemCount: _filteredOptions.length, + itemBuilder: (context, index) { + return widget.type == DropDownType.SPECIAL + ? InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Container( + height: 45, + decoration: BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: + BorderRadius.all(Radius.circular(10))), + child: Padding( + padding: EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomText(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey700)), + Icon(Icons.arrow_forward_ios, + size: 14, color: AppColors.colorNavyBlue), + ], + ), + ), + ), + ) + : Padding( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey700)), + SizedBox(height: 5), + Visibility( + visible: _filteredOptions[index].id.isNotEmpty, + child: Column( + children: [ + CustomText(_filteredOptions[index].id, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 12, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey600)), + ], + ), + ), + SizedBox(height: 5), + Divider( + thickness: 0.2, + color: AppColors.colorGrey600), + ], + ), + ), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return SizedBox(height: 10); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/Fields/field_validations.dart b/lib/app/custom_widgets/Fields/field_validations.dart new file mode 100644 index 0000000..23df0ae --- /dev/null +++ b/lib/app/custom_widgets/Fields/field_validations.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; + +import 'input_field.dart'; + +class FieldValidation { + static bool validateAll([List widgetList = const []]) { + bool isValid = true; + for (Widget widget in widgetList) { + if (widget is InputField) { + InputField inputFieldCustom = widget; + bool valid = inputFieldCustom.validate(inputFieldCustom.controller!.text); + if (!valid) { + isValid = false; + } + } + // if (widget is CustomDatePicker) { + // CustomDatePicker inputFieldCustom = widget; + // bool valid = inputFieldCustom.validate(inputFieldCustom.controller!.text); + // if (!valid) { + // isValid = false; + // } + // } + } + return isValid; + } +} diff --git a/lib/app/custom_widgets/Fields/input_field.dart b/lib/app/custom_widgets/Fields/input_field.dart new file mode 100644 index 0000000..689e196 --- /dev/null +++ b/lib/app/custom_widgets/Fields/input_field.dart @@ -0,0 +1,535 @@ +import 'dart:ui'; +import 'package:country_code_picker/country_code_picker.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../../core/constants/translation_keys.dart'; +import '../../res/app_colors.dart'; +import '../../res/app_theme.dart'; +import '../custom_dropdown.dart'; +import '../custom_text.dart'; +import 'custom_dropdown_bottom_sheet.dart'; + + +class InputField extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hintText = ""; + RxString errorTextMessage = "".obs; + final RxBool _passwordVisible = true.obs; + int? radius = 100; + EdgeInsetsGeometry? contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 15); + + // String errorText = ""; + + bool isRequired = true; + bool requiredPasswordIcon = false; + Function(String?)? onChanged; + FocusNode? focusNode = FocusNode(); + Function(DropDown?)? onItemSelected; + Rx selectedCountryCode = CountryCode().obs; + + Rx? selectedOption; + + // DropDown? selectedOption; + final bool enabled; + bool isDropDown = false; + bool isTopMarginRequired = true; + bool isCountryPicker = false; + bool isBoxDecoration = true; + bool showLabel = true; + String? dropDownType = DropDownType.NORMAL; + List? items; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType? keyboardType; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + bool isPassword = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + Widget? prefixIcon; + Widget? suffixIcon; + final DragStartBehavior dragStartBehavior; + final Function()? onClick; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + final String? prefixText; + final String? prefixCode; + final double? inputFontSize; + final FontWeight? inputFontWeight; + final Color? inputColor; + + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + + InputField({ + this.refKey, + this.controller, + this.labelText = "", + this.hintText = "", + // this.errorText = "", + this.isRequired = true, + this.requiredPasswordIcon = false, + this.isBoxDecoration = true, + this.showLabel = true, + this.isTopMarginRequired = true, + this.isDropDown = false, + this.isCountryPicker = false, + this.dropDownType, + this.inputFontSize, + this.inputFontWeight, + this.inputColor, + this.validator, + this.contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + this.items, + this.radius = 100, + this.decoration, + this.focusNode, + this.onChanged, + this.onItemSelected, + this.prefixIcon, + this.suffixIcon, + this.selectedOption, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 1, + this.showCursor = true, + this.onClick, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + this.prefixText, + this.prefixCode, + }) : errorTextMessage = "".obs { + // errorText = errorTextMessage.value; + } + + void setText(String text) { + controller!.text = text; + markFieldAsValid(); + } + + void clear() { + controller!.clear(); + markFieldAsValid(); + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + isError.value = false; + } + + void markFieldAsInvalid() { + print("============================="); + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + void setDropDownOption(DropDown option) { + selectedOption = Rx(option); + setText(selectedOption!.value.label); + markFieldAsValid(); + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: isTopMarginRequired ? 15 : 0), + Visibility( + visible: isBoxDecoration && showLabel, + child: Column( + children: [ + CustomText(labelText, style: AppThemeData.labelStyle), + const SizedBox(height: 5), + ], + ), + ), + FormBuilderTextField( + key: refKey, + name: "", + focusNode: focusNode, + decoration: isCountryPicker ? countryCodeDecoration() : (isBoxDecoration ? boxedDecoration() : normalFieldDecoration()), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + readOnly: isDropDown ? true : readOnly, + + validator: (value) { + validate(value!); + return null; + }, + onChanged: (value) { + if (value!.isNotEmpty) { + markFieldAsValid(); + } + if (onChanged != null) { + onChanged!(value); + } + }, + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + maxLengthEnforcement: maxLengthEnforcement, + textAlign: textAlign, + autofocus: isDropDown ? false : autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1, fontSize: double.parse((inputFontSize ?? "0.0").toString()) == 0 ? AppThemeData.inputStyle.fontSize : double.parse((inputFontSize ?? "0.0").toString()), fontWeight: inputFontWeight ?? AppThemeData.inputStyle.fontWeight, color: inputColor ?? AppThemeData.inputStyle.color), + controller: controller, + textInputAction: textInputAction ?? TextInputAction.done, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + onSubmitted: onSubmitted, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + // cursorWidth: 1.5, + // cursorHeight: 15, + // cursorRadius: Radius.circular(10.0), + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword && _passwordVisible.value, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: isDropDown ? false : showCursor, + onTap: () { + if (onClick != null) { + onClick!(); + } + if (isDropDown && items != null && items!.isNotEmpty) { + // + + FocusScope.of(context).requestFocus(FocusNode()); + + CustomDropDownBottomSheet().showBottomSheet(context, items!, dropDownType ?? DropDownType.NORMAL, (selectedItem) { + setText(selectedItem.label); + selectedOption = Rx(selectedItem); + if (onItemSelected != null) { + onItemSelected!(selectedItem); + } + }); + } + }, + onTapOutside: onTapOutside, + enableSuggestions: enableSuggestions, + textAlignVertical: textAlignVertical, + dragStartBehavior: dragStartBehavior, + scrollController: scrollController, + scrollPhysics: scrollPhysics, + selectionWidthStyle: selectionWidthStyle, + smartDashesType: smartDashesType, + smartQuotesType: smartQuotesType, + selectionHeightStyle: BoxHeightStyle.tight, + autofillHints: autofillHints, + obscuringCharacter: obscuringCharacter, + mouseCursor: mouseCursor, + magnifierConfiguration: magnifierConfiguration, + contentInsertionConfiguration: contentInsertionConfiguration, + spellCheckConfiguration: spellCheckConfiguration, + ), + ], + ); + }); + } + + InputDecoration normalFieldDecoration() { + return InputDecoration( + filled: true, + prefixIcon: prefixIcon, + fillColor: AppColors.transparent, + isDense: true, + contentPadding: const EdgeInsets.only(bottom: 5), + labelText: labelText, + labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + errorBorder: UnderlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value)), + focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5)), + enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5)), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText, + prefixStyle: AppThemeData.hintStyle, + suffixIcon: Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: isDropDown ? 22 : 0, + ), + ); + } + + InputDecoration boxedDecoration() { + return InputDecoration( + isDense: true, + contentPadding: contentPadding ?? const EdgeInsets.symmetric(horizontal: 15, vertical: 15) /*EdgeInsets.all(10)*/, + labelText: isBoxDecoration ? null : (labelText.isNotEmpty ? labelText : null), + labelStyle: AppThemeData.labelStyle, + prefixIcon: prefixIcon, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + // border: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(10))), + focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText, + // prefixStyle: AppThemeData.hintStyle, + suffixIcon: suffixIcon ?? addSuffixIcon(), + ); + } + + Widget? addSuffixIcon() { + if (requiredPasswordIcon) { + return IconButton( + icon: Icon(size: 18, color: AppColors.colorGrey500, _passwordVisible.value ? Icons.visibility : Icons.visibility_off_rounded), + onPressed: () { + _passwordVisible.value = !_passwordVisible.value; + }, + ); + } else if (isDropDown) { + return const Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: 22, + ); + } + return null; + } + + InputDecoration countryCodeDecoration() { + return InputDecoration( + prefixIcon: CountryCodePicker( + initialSelection: 'PK', + onInit: (code) { + selectedCountryCode.value = code!; + }, + showFlagDialog: true, + showCountryOnly: true, + countryFilter: const [ + 'pk', + 'us', + 'it', + ], + emptySearchBuilder: (context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 15), + CustomText("No Results", style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.inputLabelColor)), + ], + ); + }, + onChanged: (val) { + selectedCountryCode.value = val; + }, + + searchDecoration: InputDecoration( + filled: false, + fillColor: AppColors.transparent, + isDense: false, + alignLabelWithHint: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + errorStyle: AppThemeData.errorStyle.copyWith(color: AppThemeData.inputErrorColor), + errorBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputErrorBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + prefixStyle: AppThemeData.hintStyle, + ), + searchStyle: AppThemeData.inputStyle.copyWith(height: 1), + // textStyle: AppThemeData.inputStyle.copyWith(height: 1), + ), + isDense: true, + contentPadding: const EdgeInsets.all(10), + labelText: isBoxDecoration ? null : (labelText.isNotEmpty ? labelText : null), + labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + // focusedErrorBorder: OutlineInputBorder( + // borderSide: BorderSide(color: inputErrorBorderColor.value), + // borderRadius: const BorderRadius.all(Radius.circular(10))), + // errorBorder: OutlineInputBorder( + // borderSide: BorderSide(color: inputErrorBorderColor.value), + // borderRadius: const BorderRadius.all(Radius.circular(10))), + // focusedBorder: const OutlineInputBorder( + // borderSide: BorderSide( + // color: AppThemeData.inputFocusedBorderColor, + // width: 1.5, + // ), + // borderRadius: BorderRadius.all(Radius.circular(10))), + // enabledBorder: const OutlineInputBorder( + // borderSide: BorderSide( + // color: AppThemeData.inputEnabledBorderColor, width: 1.5), + // borderRadius: BorderRadius.all(Radius.circular(10))), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText ?? "", + prefixStyle: AppThemeData.hintStyle, + suffixIcon: Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: isDropDown ? 22 : 0, + ), + ); + } + + String getCustomText({bool isCountryCodeRequired = false, bool isPrefixRequired = false}) { + if (isCountryCodeRequired) { + if (isCountryPicker) { + return selectedCountryCode.value.dialCode! + controller!.text; + } + return controller!.text; + } else if (isPrefixRequired) { + return (prefixCode ?? "") + controller!.text; + } + return controller!.text; + } +} + +class DropDownType { + static final String NORMAL = "01"; + static final String SPECIAL = "02"; +} + +class InputType { + static final int INT_MAX_VALUE_ = 9223372036854775807; + static final FilteringTextInputFormatter NUMBER = FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')); + static final FilteringTextInputFormatter NUMBER_DECIMAL = FilteringTextInputFormatter.allow(RegExp(r'^[0-9]*\.?[0-9]*$')); + + static List maxValueFilter(int maxNumber, bool isDecimal, int decimalPoint) { + return [ + FilteringTextInputFormatter.allow(isDecimal ? RegExp(r'^\d+\.?\d{0,2}') : RegExp(r'^\d+$')), + TextInputFormatter.withFunction((oldValue, newValue) { + if (newValue.text.isEmpty) { + return newValue.copyWith(text: '', selection: const TextSelection.collapsed(offset: 0)); + } + try { + final numericValue = double.parse(newValue.text); + if (numericValue <= maxNumber) { + return newValue; + } + } catch (e) { + return newValue; + } + return oldValue; + }), + ]; + } +} diff --git a/lib/app/custom_widgets/bottom_sheet.dart b/lib/app/custom_widgets/bottom_sheet.dart new file mode 100644 index 0000000..4d4b7ce --- /dev/null +++ b/lib/app/custom_widgets/bottom_sheet.dart @@ -0,0 +1,212 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; + + +class OptionData { + String label = ""; + String code = ""; + Object dataObject = {}; + + OptionData(); + + OptionData.withData(this.label, this.code, this.dataObject); + + factory OptionData.fromJson(Map json) { + return OptionData.withData( + json['label'] ?? "", + json['code'] ?? "", + json['dataObject'], + ); + } + + Map toJson() { + return { + 'label': label, + 'code': code, + 'dataObject': dataObject, + }; + } + + @override + String toString() { + return 'OptionData{label: $label, code: $code, dataObject: $dataObject}'; + } +} + +class FilterableBottomSheet extends StatefulWidget { + final List options; + final Function(OptionData) onSelect; + + FilterableBottomSheet({required this.options, required this.onSelect}); + + @override + _FilterableBottomSheetState createState() => _FilterableBottomSheetState(); +} + +class _FilterableBottomSheetState extends State { + TextEditingController _filterTextController = TextEditingController(); + List _filteredOptions = []; + @override + void initState() { + super.initState(); + _filteredOptions.addAll(widget.options); + } + + void _updateFilteredList(String query) { + setState(() { + _filteredOptions.clear(); + if (query.isEmpty) { + _filteredOptions.addAll(widget.options); + } else { + query = query.toLowerCase(); + _filteredOptions.addAll(widget.options + .where((item) => item.label.toLowerCase().contains(query))); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(1.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 40, + padding: EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textSearch), + ), + controller: _filterTextController, + onChanged: _updateFilteredList, + ), + ), + ], + ), + ), + SizedBox(height: 20.0), + Container( + height: 300, + child: ListView.builder( + physics: const BouncingScrollPhysics(), + itemCount: _filteredOptions.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(fontSize: 12)), + SizedBox(height: 5), + Visibility( + visible: _filteredOptions[index].code.isNotEmpty, + child: Column( + children: [ + Text(_filteredOptions[index].code, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(fontSize: 10)), + ], + ), + ), + SizedBox(height: 5), + Divider(thickness: 0.2, color: AppColors.colorText), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} + +class DialogDesign extends StatelessWidget { + List options = []; + Function(OptionData) onSelect; + + DialogDesign(this.options, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectYourOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: AppColors.titleColor, + fontSize: 12, + fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); // Close the bottom sheet using Get + }, + child: CircleAvatar( + radius: 12.5, + backgroundColor: Colors.transparent, + child: Icon( + Icons.close, + size: 16.0, + color: Colors.blue, + ), + ), + ), + ], + ), + SizedBox(height: 10.0), + FilterableBottomSheet(options: options, onSelect: onSelect), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_app_bar.dart b/lib/app/custom_widgets/custom_app_bar.dart new file mode 100644 index 0000000..a5eeaad --- /dev/null +++ b/lib/app/custom_widgets/custom_app_bar.dart @@ -0,0 +1,126 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../core/constants/app_assets.dart'; +import '../res/app_colors.dart'; + + +class DashBoardAppBar extends StatelessWidget implements PreferredSizeWidget { + final String? title; + final Color titleColor; + final Color backgroundColor; + final VoidCallback onBackButtonPressed; + final List? actions; + + const DashBoardAppBar({ + Key? key, + this.title = "", + this.titleColor = Colors.white, + this.backgroundColor = AppColors.colorPrimary, + required this.onBackButtonPressed, + this.actions, + }) : super(key: key); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: backgroundColor, + elevation: 0.0, + leadingWidth: 100, + leading: Container( + margin: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50), + color: Colors.transparent, + ), + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: onBackButtonPressed, + child: Padding( + padding: const EdgeInsets.all(7.0), + child: Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY( + Directionality.of(context) == TextDirection.rtl ? 280 : 0), + child: SvgPicture.asset( + AppAssets.lg_back_arrow, + fit: BoxFit.cover, + )), + ), + ), + ), + title: Text( + title ?? "", + style: Theme.of(context) + .textTheme + .displayMedium + ?.copyWith(color: AppColors.white, fontSize: 20), + ), + actions: actions, + ); + // return ColoredBox( + // color: backgroundColor, + // child: Stack( + // children: [ + // Align( + // alignment: Directionality.of(context) == TextDirection.rtl + // ? Alignment.centerRight + // : Alignment.centerLeft, + // child: Container( + // margin: const EdgeInsets.all(10), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(50), + // color: Colors.transparent, + // ), + // width: 66.0, + // height: 32.0, + // child: Material( + // color: Colors.transparent, + // child: InkWell( + // borderRadius: const BorderRadius.all(Radius.circular(50)), + // splashColor: Colors.transparent, + // onTap: onBackButtonPressed, + // child: Padding( + // padding: const EdgeInsets.all(7.0), + // child: Transform( + // alignment: Alignment.center, + // transform: Matrix4.rotationY( + // Directionality.of(context) == TextDirection.rtl ? 280 : 0), + // child: SvgPicture.asset( + // AppAssets.ic_back_arrow_appbar, + // fit: BoxFit.cover, + // )), + // ), + // ), + // ), + // ), + // ), + // Center( + // child: Text( + // title ?? "", + // style: Theme.of(context) + // .textTheme + // .displayMedium + // ?.copyWith(color: AppColors.white, fontSize: 20), + // ), + // ), + // Align( + // alignment: Directionality.of(context) == TextDirection.rtl + // ? Alignment.centerLeft + // : Alignment.centerRight, // Align to the right + // child: Center( + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [...actions ?? []], + // ), + // ), + // ), + // ], + // ), + // ); + } +} diff --git a/lib/app/custom_widgets/custom_button.dart b/lib/app/custom_widgets/custom_button.dart new file mode 100644 index 0000000..f63659f --- /dev/null +++ b/lib/app/custom_widgets/custom_button.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +class CustomButton extends StatelessWidget { + final VoidCallback onPressed; + final String buttonText; + final Color buttonColor; + final EdgeInsets buttonPadding; + final EdgeInsets iconPadding; + final Widget? icon; + final TextStyle? textStyle; + final double radius; + final BorderSide? sideBorder; + const CustomButton({ + Key? key, + required this.onPressed, + required this.buttonText, + required this.buttonColor, + this.radius = 50, + this.buttonPadding = const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + this.iconPadding = const EdgeInsets.only(right: 0), + this.icon, + this.textStyle, + this.sideBorder, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + padding: buttonPadding, + backgroundColor: buttonColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius), + side: sideBorder ?? BorderSide.none, + ), + elevation: 0.0, + alignment: Alignment.center, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (icon != null) ...[ + Padding( + padding: iconPadding, + child: icon, + ), + ], + Text( + buttonText, + style: textStyle ?? + Theme.of(context).textTheme.labelLarge?.copyWith( + color: Colors.white, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_date_time_picker.dart b/lib/app/custom_widgets/custom_date_time_picker.dart new file mode 100644 index 0000000..8eaba34 --- /dev/null +++ b/lib/app/custom_widgets/custom_date_time_picker.dart @@ -0,0 +1,298 @@ +import 'dart:ui'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +class CustomDateTimePicker extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hint = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType keyboardType; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + bool isPassword = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + TextStyle? labelStyle; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + final DragStartBehavior dragStartBehavior; + final GestureTapCallback? onTap; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + final bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + + final Rx fillColor = Rx(Colors.transparent); + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + + CustomDateTimePicker({ + this.refKey, + this.controller, + this.labelText = "", + this.hint = "", + this.errorText = "", + this.labelStyle, + this.isRequired = true, + this.validator, + this.decoration, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType = TextInputType.text, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 4, + this.showCursor = true, + this.onTap, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void setTest(String errorMessage) { + this.controller!.text = errorMessage; + // inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + // inputErrorColor.value = AppThemeData.inputErrorColor; + // fillColor.value = AppThemeData.inputErrorColor; + // errorTextMessage.value = errorMessage; + // isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + fillColor.value = Colors.transparent; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = + TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderDateTimePicker( + key: refKey, + name: "", + initialEntryMode: DatePickerEntryMode.calendar, + inputType: InputType.date, + + initialDatePickerMode: DatePickerMode.day, + onChanged: (value) { + if (value.toString().isNotEmpty) { + markFieldAsValid(); + } + }, + // format: DateFormat('dd-yyyy-MM'), + currentDate: DateTime.now(), + firstDate: DateTime(1970), + lastDate: DateTime(2030), + decoration: InputDecoration( + suffixIcon: Container( + width: 30, + height: 30, + margin: const EdgeInsets.all(5), + child: const Icon(size: 18, Icons.calendar_month_rounded), + ), + filled: true, + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + labelText: null, + // labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle + .copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputEnabledBorderColor), + borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputFocusedBorderColor), + borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: + const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputErrorBorderColor), + borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty + ? null + : errorTextMessage.value, + hintText: hint, + hintStyle: AppThemeData.hintStyle, + ), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + textAlign: textAlign, + autofocus: autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1), + controller: controller, + textInputAction: textInputAction, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: showCursor, + mouseCursor: mouseCursor, + ), + ], + ); + }); + } + + String getText() { + return this.controller!.text; + } +} diff --git a/lib/app/custom_widgets/custom_dialog.dart b/lib/app/custom_widgets/custom_dialog.dart new file mode 100644 index 0000000..b6536ac --- /dev/null +++ b/lib/app/custom_widgets/custom_dialog.dart @@ -0,0 +1,605 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../core/constants/app_assets.dart'; +import '../core/constants/translation_keys.dart'; +import '../core/utils/app_utils.dart'; +import '../models/TransactionSubmitRequestModel.dart'; +import '../res/app_colors.dart'; +import '../res/app_dimensions.dart'; +import '../routes/app_pages.dart'; +import 'custom_button.dart'; + + +class CustomDialog { + /// SuccessFull Dialog...........Transactions + + static _showBasicDialog(Widget child) { + Get.dialog(responsiveWidget(child), barrierDismissible: false); + } + + /// Warning Dialog + static showWarningDialog({ + //required String title, + required String description, + // Function()? onTapPositive, + required Function() onTapNegative, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.topLeft : Alignment.topRight, + child: GestureDetector( + onTap: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 14, + width: 14, + ))), + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_featured, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_close, + height: 6, + width: 6, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWarning), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + const SizedBox(height: 20), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () { + onTapNegative(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textYes), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.black), + buttonColor: AppColors.colorSkipBtn, + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Error Dialog + static showErrorDialog({ + //required String title, + required String description, + // Function()? onClosePress, + required Function() onTapNegative, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.topLeft : Alignment.topRight, + child: GestureDetector( + onTap: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 14, + width: 14, + ))), + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_featured, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_close, + height: 6, + width: 6, + ), + ), + ], + ), + ), + const SizedBox(width: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textError), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + const SizedBox(height: 20), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () { + onTapNegative(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Success Dialog + static showSuccessDialog({ + String? title, + required String description, + required Function() onTapPositive, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + if (title != null) ...[ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + title, + style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey800), + ), + ), + const SizedBox(height: 10), + ], + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + onTapPositive(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + buttonColor: AppColors.colorButton, + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + + /// Information Dialog + static showInfoDialog({ + required String title, + required String description, + required Function() onTapPositive, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_congratulations, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_correct_icon, + height: 22, + width: 22, + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textInform), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () { + onTapPositive(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Information Dialog + static showLogoutDialog({ + required Function() onTapPositive, + required Function() onTapNegative, + required BuildContext context, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOutContent), style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapNegative, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCancel), + buttonColor: AppColors.red, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + SizedBox(width: 15), + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapPositive, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Alert Dialog + static showAlertDialog({ + required Function() onTapPositive, + required Function() onTapNegative, + required BuildContext context, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Image.asset( + AppAssets.ic_warning, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textWarning), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWarningContent), style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapNegative, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCancel), + buttonColor: AppColors.red, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + const SizedBox(width: 15), + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapPositive, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDelete), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + static showGeneralDialog({ + required String title, + required String description, + required Widget child, + }) { + _showBasicDialog(child); + } + + static void showTransactionSuccessDialog(BuildContext context, String endingBalance, String exchangeRate, TransactionSubmitRequestModel transactionSubmitRequestModel) { + Get.dialog( + responsiveWidget( + Stack( + children: [ + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Image.asset(AppAssets.ic_launcher, height: 80, width: 80), + Padding( + padding: const EdgeInsets.only(top: 20), + child: Align(alignment: Alignment.center, child: Text(TranslationKeys.makeTranslation(TranslationKeys.textSuccess), style: Theme.of(context).textTheme.titleMedium)), + ), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textRecipient), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textMessage), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textEndingBalance), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + const SizedBox(width: 20), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(transactionSubmitRequestModel.crMbmBkmstitle, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(transactionSubmitRequestModel.otdTrancomment, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(AppUtils.showAmountWithCurr(transactionSubmitRequestModel.sgtGntramtfc.toString(), transactionSubmitRequestModel.crPcrCurrcode), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(exchangeRate, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(endingBalance, style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 80), + child: CustomButton( + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/custom_widgets/custom_dropdown.dart b/lib/app/custom_widgets/custom_dropdown.dart new file mode 100644 index 0000000..c0e3f97 --- /dev/null +++ b/lib/app/custom_widgets/custom_dropdown.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +@immutable +class CustomDropDown extends GetView { + RxList listData = RxList.empty(); + GlobalKey? refKey; + String labelText = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + InputDecoration? decoration; + TextStyle? labelStyle; + final TextStyle? style; + final AutovalidateMode autovalidateMode; + TextEditingController? controller; + TextInputType keyboardType; + final TextCapitalization textCapitalization; + final bool readOnly; + + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + DropDown? selectedOption = null; + + CustomDropDown({ + this.refKey, + required this.listData, + this.controller, + this.labelText = "", + this.errorText = "", + this.isRequired = true, + this.decoration, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.readOnly = false, + this.textCapitalization = TextCapitalization.none, + this.keyboardType = TextInputType.text, + this.style, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + DropDown? getSelectedOption() { + return selectedOption; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate() { + if (isRequired) { + if (selectedOption == null) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderDropdown( + name: '', + isDense: true, + isExpanded: false, + elevation: 2, + decoration: InputDecoration( + filled: true, + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 12), + labelText: null, + // labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor), borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor), borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputErrorBorderColor), borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + // hintText: hint, + + hintStyle: AppThemeData.hintStyle, + ), + borderRadius: const BorderRadius.all(Radius.circular(5)), + dropdownColor: AppColors.colorGrey200, + focusColor: Colors.transparent, + + items: listData.map((data) { + return DropdownMenuItem( + value: data, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 0), + child: CustomText( + data.label, + style: AppThemeData.inputStyle.copyWith(height: 1), + ), + ), + ); + }).toList(), + onChanged: (val) { + selectedOption = val!; + markFieldAsValid(); + }, + onTap: () {}, + valueTransformer: (val) => val?.toString(), + ), + ], + ); + }); + } +} + +class DropDown { + String id = ""; + String label = ""; + dynamic data = {}; + + DropDown(this.id, this.label, [this.data = const {}]); + + DropDown.empty() + : this.id = "", + this.label = "", + this.data = {}; + + @override + String toString() { + return 'DropDown{id: $id, label: $label, data: $data}'; + } +} diff --git a/lib/app/custom_widgets/custom_input_field.dart b/lib/app/custom_widgets/custom_input_field.dart new file mode 100644 index 0000000..fa924b5 --- /dev/null +++ b/lib/app/custom_widgets/custom_input_field.dart @@ -0,0 +1,330 @@ +import 'dart:ui'; + +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +@immutable +class CustomInputFieldCustom extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hint = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType keyboardType; + EdgeInsets? padding = EdgeInsets.zero; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + + bool isPassword = false; + bool requiredPasswordIcon = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + TextStyle? labelStyle; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + final DragStartBehavior dragStartBehavior; + final GestureTapCallback? onTap; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + final bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + + final Rx fillColor = Rx(Colors.transparent); + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + RxBool passwordVisible = false.obs; + + CustomInputFieldCustom({ + this.refKey, + this.controller, + this.labelText = "", + this.hint = "", + this.errorText = "", + this.isRequired = true, + this.validator, + this.labelStyle, + this.decoration, + this.padding, + this.enabled = true, + this.requiredPasswordIcon = false, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType = TextInputType.text, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 4, + this.showCursor = true, + this.onTap, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + fillColor.value = Colors.transparent; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = + TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderTextField( + key: refKey, + name: "", + + decoration: InputDecoration( + filled: true, + suffixIcon: Visibility( + visible: requiredPasswordIcon, + child: Container( + width: 30, + height: 30, + margin: const EdgeInsets.all(5), + child: IconButton( + icon: Icon( + size: 18, + passwordVisible.value + ? Icons.visibility + : Icons.visibility_off_rounded), + onPressed: () { + passwordVisible.value = !passwordVisible.value; + }, + ), + ), + ), + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: padding ?? + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + labelText: null, + errorStyle: AppThemeData.errorStyle + .copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputEnabledBorderColor), + borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputFocusedBorderColor), + borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: + const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputErrorBorderColor), + borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty + ? null + : errorTextMessage.value, + hintText: hint, + hintStyle: AppThemeData.hintStyle, + ), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + readOnly: readOnly, + validator: (value) { + validate(value!); + return null; + }, + onChanged: (value) { + if (value!.isNotEmpty) { + markFieldAsValid(); + } + }, + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + maxLengthEnforcement: maxLengthEnforcement, + textAlign: textAlign, + autofocus: autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1), + controller: controller, + textInputAction: textInputAction, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + onSubmitted: onSubmitted, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + cursorWidth: 1.5, + cursorHeight: 15, + cursorRadius: const Radius.circular(10.0), + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword && passwordVisible.value, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: showCursor, + onTap: onTap, + onTapOutside: onTapOutside, + enableSuggestions: enableSuggestions, + textAlignVertical: textAlignVertical, + dragStartBehavior: dragStartBehavior, + scrollController: scrollController, + scrollPhysics: scrollPhysics, + selectionWidthStyle: selectionWidthStyle, + smartDashesType: smartDashesType, + smartQuotesType: smartQuotesType, + selectionHeightStyle: selectionHeightStyle, + autofillHints: autofillHints, + obscuringCharacter: obscuringCharacter, + mouseCursor: mouseCursor, + magnifierConfiguration: magnifierConfiguration, + contentInsertionConfiguration: contentInsertionConfiguration, + spellCheckConfiguration: spellCheckConfiguration, + ), + ], + ); + }); + } + + String getText() { + return controller!.text; + } + + void clear() { + controller!.clear(); + } +} diff --git a/lib/app/custom_widgets/custom_label.dart b/lib/app/custom_widgets/custom_label.dart new file mode 100644 index 0000000..8e58f78 --- /dev/null +++ b/lib/app/custom_widgets/custom_label.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +import 'package:google_fonts/google_fonts.dart'; + +import '../res/app_colors.dart'; + +class LabelText extends StatelessWidget { + final String text; + final EdgeInsets margin; + final Color labelColor; + final bool underLineColor; + final double fontSize; + final bool underline; + final FontWeight fontWeight; + final bool fontFamily; + final TextStyle? style; + LabelText( + this.text, { + this.margin = EdgeInsets.zero, + this.labelColor = AppColors.colorTitle, + this.underLineColor = false, + this.fontSize = 18, + this.underline = false, + this.fontWeight = FontWeight.w600, + this.fontFamily = false, + this.style, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Text( + text, + maxLines: 3, + textAlign: TextAlign.center, + style: style ?? + TextStyle( + color: labelColor, + fontSize: fontSize, + fontFamily: fontFamily ? GoogleFonts.roboto().toString() : "", + fontWeight: fontWeight, + decoration: + underline ? TextDecoration.underline : TextDecoration.none, + decorationColor: + underLineColor ? AppColors.colorTitle : Colors.transparent, + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_no_record.dart b/lib/app/custom_widgets/custom_no_record.dart new file mode 100644 index 0000000..f0cf07f --- /dev/null +++ b/lib/app/custom_widgets/custom_no_record.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class CustomNoRecord extends StatelessWidget { + final String title; + final String description; + final Widget? icon; + + const CustomNoRecord({ + Key? key, + required this.title, + required this.description, + this.icon, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 40), + SvgPicture.asset("assets/uco/icons/ic_no_result.png",width: 100, height: 100,), + SizedBox(height: 10), + Text(title, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontWeight: FontWeight.w500)), + SizedBox(height: 10), + Text(description, style: Theme.of(context).textTheme.bodySmall), + ], + ); + } +} diff --git a/lib/app/custom_widgets/custom_text.dart b/lib/app/custom_widgets/custom_text.dart new file mode 100644 index 0000000..e4596d5 --- /dev/null +++ b/lib/app/custom_widgets/custom_text.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../res/app_colors.dart'; +import '../res/app_dimensions.dart'; +import '../res/app_theme.dart'; + + +class CustomText extends StatelessWidget { + final String text; + final EdgeInsets margin; + final EdgeInsets padding; + final Color labelColor; + final bool underLineColor; + final double fontSize; + final bool underline; + final TextStyle? style; + final FontWeight fontWeight; + final bool fontFamily; + final TextAlign textAlign; + final TextOverflow? overflow; + + const CustomText( + this.text, { + super.key, + this.margin = EdgeInsets.zero, + this.style = const TextStyle(), + this.padding = EdgeInsets.zero, + this.labelColor = AppThemeData.textFieldsColor, + this.underLineColor = false, + this.fontSize = -1, + this.underline = false, + this.fontWeight = FontWeight.w400, + this.fontFamily = false, + this.textAlign = TextAlign.start, + this.overflow, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: margin, + padding: padding, + child: Text( + text, + textAlign: textAlign, + overflow: overflow ?? TextOverflow.clip, + style: style ?? + Theme.of(context).textTheme.labelMedium?.copyWith( + color: labelColor, + fontFamily: fontFamily ? GoogleFonts.inter().toString() : "", + fontSize: + fontSize == -1 ? AppDimensions.customTextSize : fontSize, + fontWeight: fontWeight, + decoration: underline + ? TextDecoration.underline + : TextDecoration.none, + decorationColor: underLineColor + ? AppColors.titleColor + : Colors.transparent, + ), + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_toasty.dart b/lib/app/custom_widgets/custom_toasty.dart new file mode 100644 index 0000000..1d4443a --- /dev/null +++ b/lib/app/custom_widgets/custom_toasty.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class Toasty { + static error(String msg) { + _showToast(msg, Colors.red); + } + + static success(String msg) { + _showToast(msg, Colors.green); + } + + static _showToast(String msg, Color bgColor) { + Fluttertoast.showToast(msg: msg, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 1, backgroundColor: bgColor, textColor: Colors.white); + } +} diff --git a/lib/app/custom_widgets/date_picker.dart b/lib/app/custom_widgets/date_picker.dart new file mode 100644 index 0000000..53f85ec --- /dev/null +++ b/lib/app/custom_widgets/date_picker.dart @@ -0,0 +1,94 @@ +import 'package:calendar_date_picker2/calendar_date_picker2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart'; +import 'package:get/get.dart'; + +import '../res/app_colors.dart'; + + +class DatePicker { + static Future showDatePicker(BuildContext context) async { + return await showRoundedDatePicker( + borderRadius: 10, + context: context, + onTapDay: (date, test) { + return true; + }, + textPositiveButton: "Yes", + theme: ThemeData( + primarySwatch: Colors.green, + ), + styleDatePicker: MaterialRoundedDatePickerStyle( + textStyleDayButton: + const TextStyle(fontSize: 25, color: Colors.white), + textStyleYearButton: const TextStyle( + fontSize: 15, + color: Colors.white, + ), + textStyleDayHeader: const TextStyle( + fontSize: 14, + color: AppColors.colorPrimary, + ), + backgroundHeader: AppColors.colorPrimary, + textStyleCurrentDayOnCalendar: const TextStyle( + fontSize: 12, color: Colors.grey, fontWeight: FontWeight.normal), + textStyleDayOnCalendar: + TextStyle(fontSize: 12, color: Colors.black.withOpacity(0.9)), + textStyleDayOnCalendarSelected: TextStyle( + fontSize: 12, + color: AppColors.white.withOpacity(0.9), + fontWeight: FontWeight.bold), + textStyleDayOnCalendarDisabled: + TextStyle(fontSize: 12, color: Colors.grey.withOpacity(0.1)), + textStyleMonthYearHeader: TextStyle( + fontSize: 12, + color: Colors.black.withOpacity(0.9), + fontWeight: FontWeight.bold), + + // paddingDatePicker: EdgeInsets.all(0), + // paddingMonthHeader: EdgeInsets.all(15), + paddingActionBar: const EdgeInsets.all(5), + paddingDateYearHeader: const EdgeInsets.all(10), + sizeArrow: 20, + colorArrowNext: Colors.black.withOpacity(0.9), + colorArrowPrevious: Colors.black.withOpacity(0.9), + marginLeftArrowPrevious: 8, + marginTopArrowPrevious: 8, + marginTopArrowNext: 8, + marginRightArrowNext: 8, + // textStyleButtonAction: TextStyle(fontSize: 208, color: Colors.white), + textStyleButtonPositive: const TextStyle( + fontSize: 15, color: Colors.white, fontWeight: FontWeight.bold), + textStyleButtonNegative: + TextStyle(fontSize: 15, color: Colors.white.withOpacity(0.5)), + decorationDateSelected: const BoxDecoration( + color: AppColors.colorPrimary, shape: BoxShape.circle), + backgroundPicker: AppColors.white.withOpacity(0.9), + backgroundActionBar: AppColors.colorPrimary.withOpacity(0.9), + // backgroundHeaderMonth: AppColors.primary.withOpacity(0.9), + ), + styleYearPicker: MaterialRoundedYearPickerStyle( + textStyleYear: const TextStyle(fontSize: 20, color: Colors.grey), + textStyleYearSelected: const TextStyle( + fontSize: 20, color: Colors.grey, fontWeight: FontWeight.bold), + heightYearRow: 30, + backgroundPicker: AppColors.colorPrimary.withOpacity(0.3), + )); + + // Toasty.success("--------->>> " + newDateTime.toString()); + } + + static Future?> showRangeDatePicker() async { + return showCalendarDatePicker2Dialog( + context: Get.context!, + config: CalendarDatePicker2WithActionButtonsConfig( + calendarType: CalendarDatePicker2Type.range, + allowSameValueSelection: false, + currentDate: DateTime.now(), + firstDate: DateTime(2020), + lastDate: DateTime.now().add(Duration(days: 1)), + ), + dialogSize: Size(Get.width, 150), + ); + } +} diff --git a/lib/app/custom_widgets/pop_dialog.dart b/lib/app/custom_widgets/pop_dialog.dart new file mode 100644 index 0000000..d0fed62 --- /dev/null +++ b/lib/app/custom_widgets/pop_dialog.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:quickalert/models/quickalert_type.dart'; +import 'package:quickalert/widgets/quickalert_dialog.dart'; + +import '../core/constants/translation_keys.dart'; +import '../core/extensions/build_context_ext.dart'; +import '../res/app_colors.dart'; + + +class PopDialog { + static late BuildContext dialogContext; + + static successDialog( + BuildContext context, { + String title = "", + String description = "An Success occurred", + String positiveButtonText = "", + Function()? onPositiveTap, + }) { + QuickAlert.show( + context: context, + title: title.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textSuccess) : title, + text: description, + confirmBtnColor: AppColors.colorButton, + confirmBtnTextStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorSecondary), + confirmBtnText: positiveButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textOK) : positiveButtonText, + onConfirmBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onPositiveTap != null) { + onPositiveTap(); + } + }, + disableBackBtn: true, + type: QuickAlertType.success, + barrierDismissible: false, + showConfirmBtn: true, + ); + } + + static warningDialog( + BuildContext context, { + String title = "", + String description = "", + String positiveButtonText = "", + String negativeButtonText = "", + Function()? onPositiveTap, + Function()? onNegativeTap, + }) { + QuickAlert.show( + showCancelBtn: true, + context: context, + title: title.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textWarning) : title, + confirmBtnColor: AppColors.colorButton, + text: description, + confirmBtnTextStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorSecondary), + confirmBtnText: positiveButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textOK) : positiveButtonText, + cancelBtnText: negativeButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textCancel) : negativeButtonText, + onCancelBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onNegativeTap != null) { + onNegativeTap(); + } + }, + onConfirmBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onPositiveTap != null) { + onPositiveTap(); + } + }, + disableBackBtn: true, + type: QuickAlertType.warning, + barrierDismissible: false, + showConfirmBtn: true, + ); + } + + static Card buildButton({ + required onTap, + required title, + required text, + required leadingImage, + }) { + return Card( + shape: const StadiumBorder(), + margin: const EdgeInsets.symmetric( + horizontal: 20, + ), + clipBehavior: Clip.antiAlias, + elevation: 1, + child: ListTile( + onTap: onTap, + leading: CircleAvatar( + backgroundImage: AssetImage( + leadingImage, + ), + ), + title: Text( + title ?? "", + ), + subtitle: Text(text ?? "", style: Get.context.textTheme.bodySmall), + trailing: const Icon( + Icons.keyboard_arrow_right_rounded, + ), + ), + ); + } +} diff --git a/lib/app/custom_widgets/responsive_widget.dart b/lib/app/custom_widgets/responsive_widget.dart new file mode 100644 index 0000000..59fc565 --- /dev/null +++ b/lib/app/custom_widgets/responsive_widget.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../routes/app_pages.dart'; + +showCutomBottomSheet(Widget child) { + Get.bottomSheet( + responsiveWidget( + InkWell( + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () { + Get.back(); + }, + child: Align( + alignment: Alignment.bottomCenter, + child: GestureDetector( + behavior: HitTestBehavior.deferToChild, + onTap: () {}, + child: child, + ), + ), + ), + ), + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} diff --git a/lib/app/custom_widgets/widget_interactions.dart b/lib/app/custom_widgets/widget_interactions.dart new file mode 100644 index 0000000..b527460 --- /dev/null +++ b/lib/app/custom_widgets/widget_interactions.dart @@ -0,0 +1,43 @@ +// import 'package:mfsys_include_app/app/core/constants/app_constants.dart'; +// import 'package:mfsys_include_app/app/core/constants/widget_types.dart'; +// import 'package:mfsys_include_app/app/presentations/widgets/parent_widget.dart'; +// import 'package:mfsys_include_app/app/presentations/widgets/widget_operation.dart'; +// import 'package:uco_ciihive/app/core/constants/widget_types.dart'; +// import 'package:uco_ciihive/app/custom_widgets/custom_input_field.dart'; +// import 'package:uco_ciihive/app/custom_widgets/widget_operation.dart'; +// +// import 'custom_text_field.dart'; +// import 'otp_pin.dart'; +// +// class WidgetInteractions { +// static Map map = {}; +// +// WidgetInteractions._privateConstructor() { +// _registerWidgets(); +// } +// +// static WidgetInteractions instance = WidgetInteractions._privateConstructor(); +// +// _registerWidgets() { +// map[WidgetTypes.CUSTOM_EDIT_TEXT] = CustomInputFieldCustom(); +// } +// +// bool validateWidget(ParentWidget field, String type) { +// return map[type]!.validate(field); +// } +// +// Object getValue(ParentWidget field, String type) { +// return map[type]!.getValue(field); +// } +// +// static bool validateAll([List args = const []]) { +// bool hasError = false; +// for (ParentWidget inputField in args) { +// bool isError = WidgetInteractions.instance.validateWidget(inputField, inputField.tags[AppConstants.FIELD_TYPE].toString()); +// if (isError) { +// hasError = true; +// } +// } +// return hasError; +// } +// } diff --git a/lib/app/custom_widgets/widget_operation.dart b/lib/app/custom_widgets/widget_operation.dart new file mode 100644 index 0000000..e079f04 --- /dev/null +++ b/lib/app/custom_widgets/widget_operation.dart @@ -0,0 +1,7 @@ +import 'package:flutter/cupertino.dart'; + +abstract class WidgetOperations { + bool validate(Widget widget); + + Object getValue(Widget widget); +} diff --git a/lib/app/l10n/Arabic.dart b/lib/app/l10n/Arabic.dart new file mode 100644 index 0000000..bf8ed2e --- /dev/null +++ b/lib/app/l10n/Arabic.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import 'package:get/get_navigation/src/root/internacionalization.dart'; + +class Arabic extends Translations { + @override + Map> get keys => { + 'ar_SA': { + "textWelcomeToJoin": "Welcome to Join Us", + "textIntroDescription": "Send money through Send Money World with best and low rate to your family, friends in two mintes.", + }, + }; +} diff --git a/lib/app/l10n/English.dart b/lib/app/l10n/English.dart new file mode 100644 index 0000000..4a73ad9 --- /dev/null +++ b/lib/app/l10n/English.dart @@ -0,0 +1,382 @@ +import 'package:get/get.dart'; + +class English extends Translations { + @override + Map> get keys => { + 'en_US': { + "textWelcomeToJoin": "Welcome to Join Us", + "textIntroDescription": "Send money through Send Money World with best and low rate to your family, friends in two mintes.", + "textLogin": "Login", + "textInternetConnectivity": "No Internet Connectivity", + "textInternalAccountTransaction": "Internal Transaction", + "textReferenceCode": "Reference Code", + "textRegister": "Register", + "textFindUAgent": "UAgent", + "textQRPay": "QR Pay", + "textAddAccount": "Add Account", + "textCreateAccount": "Create Account", + "textHelp": "Help", + "textContactUs": "Contact Us", + "textGetInTouch": "Get In Touch", + "textEmail": "Email", + "textPhone": "Phone", + "textOTPDescription": "To verify your identity we sent a verification SMS Please enter the code we sent to", + "textOTP": "OTP", + "textOTPValid": "OTP is valid till:", + "textResend": "Resend", + "textVerify": "Verify", + "textCongratulations": "Congratulations!", + "textCongratulationsContent": "Congratulations! you received money successfully.", + "textOTPMessage": "Your OTP code has been verified via email. Thanks", + "textContinue": "Continue", + "textAccountTitle": "Bilal Sabir", + "textAccountSession": "Last Login 23-Apr-2024 ", + "textSuccess": "Success", + "textOK": "OK", + "textWarning": "Warning!!", + "textCancel": "Cancel", + "textReverse": "Reverse", + "textConformation": "Confirmation", + "textLogOutContent": "Are you sure you want to log out?", + "textManage": "Manage", + "textLogout": "Log Out", + "textVersion": "version 0.0.1", + "textMyAccount": "My Account", + "textBillManagement": "Bill Management", + "textChequeManagement": "Cheque Management", + "textBeneficiaryManagement": "Beneficiary Management", + "textUSend": "U-Send", + "textUReceived": "U-Received", + "textAgentLocation": "Agent Location", + "textAccountStatement": "Account Statement", + "textSupport": "Support", + "textUserProfile": "User Profile", + "textUserActivity": "User Activity", + "textLogOut": "Logout", + "textUCash": "U Cash", + "textUShop": "U-Shop", + "textOverView": "Overview", + "textDashboardWelcomeUser": "Welcome Ahsan Raja", + "textTotalAvailableFunds": "Total Available Funds", + "textTotalAvailableBalance": "\$1000.0", + "textTotalAvailableBalanceInWords": "Sixty Eight Thousand Nine Hundred", + "textAccountNumber": "12345***89", + "textPleaseSelectAccount": "Please Select Account", + "textStatementDetails": "Statement Details", + "textBalance": "Balance", + "textUPrimary": "UPrimary", + "textUSave": "USave", + "textUChaChing": "UChaChing", + "textAboutUs": "About Us", + "textCareer": "Career", + "textWHY": "WHY", + "textWHAT": "WHAT", + "textWHYDescription": "“Maricel Jacobe arrived at 6 a.m. at one Western Union outlet to collect some wired money on Monday, only to be told she was 729th in line. Six hours later she was still waiting her turn to pick up the \$25 family members in Manila had sent her. She will have to do it again the following day, she said, because her family could only send a little at a time. Like many people in the region, she had money but couldn’t access it because the island’s banking system has been largely shut down.", + "textWHATDescription": "UCO is Universal Cash Online, a patent protected financial technology solution by AIR 1, Inc. UCO lets its users and merchants send, receive, and spend cash both online and offline. UCO solves the issues caused by current payment solutions through its free mobile platform available to 6.8 billion mobile phone subscriptions worldwide, reducing cost; time; and inconvenience. You can manage funds across multiple currencies, family budgets, business finances; pay locally; buy globally, and more.", + "textWHO": "WHO", + "textWHODescription": "The UCO team members are experienced and tested executives capable of executing this impact oriented initiative of global magnitude. We have decades of expertise in financial and mobile technology, cybercrime prevention, security, compliance, consumer goods, marketing, and advertising. We are also backed by advisors who are former Fortune 50 chief officers in the areas of: technology, banking, and finance.", + "textApply": "Apply", + "textJobTitle": "Senior ui/ux designer", + "textOfficeAddress": "Islamabad, Pakistan", + "textJobSkills": "Photoshop, Adobe XD,Invision, Figma", + "textSelectPersonalAccount": "Select Personal Account", + "textRecipientDetail": "Recipient Detail", + "textPhoneNumber": "Phone Number", + "textRecipientCardName": "Recipient Name", + "textSelectCurrency": "Select Currency", + "textSendingAmount": "Sending amount", + "textExchangeRate": "Exchange rate", + "textMessageMemo": "Message/Memo", + "textSend": "Send", + "textClear": "Clear", + "textPermissionDenied": "Permission Denied", + "textMyProfile": "My Profile", + "textNotFound": "Not Found", + "textRecipient": "Recipient", + "textHome": "Home", + "textCurrency": "Currency", + "textMessage": "Message", + "textConfirm": "Confirm", + "textEndingBalance": "Ending Balance", + "textPendingRemittance": "Pending Remittance", + "textReceived": "U-Received", + "textPinCode": "Pin Code", + "textBack": "Back", + "textCancelDescription": "Are you Sure you want to Cancel", + "textYes": "Yes", + "textUserName": "User Name", + "textPassword": "Password", + "textConfirmPassword": "Confirm Password", + "textEmailID": "Email ID", + "textCellNumber": "Cell Number", + "textNext": "Next", + "textName": "Name", + "textAddress": "Address", + "textIdentityNumber": "Identity Number", + "textSSNTaxPayerID": "SSN/TaxPayer ID", + "textPassportAlienID": "Passport # Alien ID", + "textChooseDocumentType": "Choose Document Type", + "textCNIC": "CNIC", + "textDivingLicense": "Diving License", + "textPassport": "Passport", + "textFront": "Front", + "textSkipKYC": "Skip KYC", + "textDocumentsDescription": "Official Documents Accepted as Proof of identity", + "textSignUpDescriptionDailog": "Thank you so much! Your account as been successfully registered.", + "textNotRegisterUser": "New Register User ?", + "textRegisterNow": "Register Now!", + "textSingUp": "Sign Up", + "textUploadKYC": "Upload KYC", + "textTransactionHistory": "Transaction History", + "ERR_USER_0001": "Email Already Registered", + "ERR_USER_0002": "Old Password not allowed", + "ERR_USER_0004": "User not found", + "ERR_CONNECTION": "NO internet connection", + "ERR_USER_0003": "Invalid OTP", + "ERR_USER_0005": "Invalid Credentials", + "ERR_USER_0006": "Same password cannot be set as new password", + "ERR_USER_0007": "Application is pending", + "ERR_USER_0008": "Old pin is incorrect", + "ERR_USER_0009": "Account Not Found", + "ERR_DEP_B_0001": "Account has insufficient balance", + "ERR_USER_0010": "Same cr dr account not allowed", + "ERR_USER_0011": "Phone number already registered", + "ERR_TRN_0013": "Reference Number for the Transaction not valid", + "ERR_USER_0012": "Same transaction pin cant be set as new", + "ERR_USER_0013": "Beneficiary already exists", + "ERR_TRN_0014": "Invalid transaction amount", + "textUserActivityTitle": "User Activity", + "textUserActivityChannel": "Channel: ", + "textUserActivityDevice": "Device", + "changepassword": "Change Password", + "resetPasswordMessage": "Your Password is change successfully", + "textChangePassword": "Change Password", + "textSelectFromDateAndProceed": "Select from date first and then proceed", + + /// import from include app + "textMapLocationTitle": "Map Location", + "textNormalMap": "Normal", + "textSatelliteMap": "Satellite", + "textHybridMap": "Hybrid", + "textMapContactNumber": "Contact Number", + "transUtilityBill": "Bill Payments", + "transUtilityBillCategory": "Bill Payments", + "textSelectBillType": "Select Bill Type", + "transUtilityElectricity": "Electricity", + "transUtilityGas": "Gas", + "transUtilityInternet": "Internet", + "transUtilityPTCL": "PTCL", + "transUtilityWater": "Water", + "transUtilityCreditCard": "Credit Card", + "textSelectCompany": "Select Company", + "transUtilityAJKBARKIYAT": "AJK-BARKIYAT", + "transUtilityFESCO": "FESCO", + "transUtilityGBBARKIYAT": "GB-BARKIYAT", + "transUtilityGEPCO": "GEPCO", + "transUtilityHESCO": "HESCO", + "transUtilityIESCO": "IESCO", + "textChequeBookActivation": "Cheque Book Active", + "textChequeBookActivationDialogMsg": "Successfully Cheque Book Activation Request", + "textActivationContent": "Enter the cheque numbers of the first and last leaves of your cheque book", + "textAccount": "Account", + "textAccountNumber": "Account Number", + "textBillDetailCustomerName": "MUHAMMAD BILAL", + "textFirstLeaf": "Cheque Number of First Leaf", + "textLastLeaf": "Cheque Number of Last Leaf", + "textEnterChequeNumber": "Enter cheque number", + "textChequeRequestDetail": "Cheque Book Request", + "textChequeBookRequestContent": "Please check your Details according to your inputs", + "transPakGasAgency": "Pak Gas Agency", + "transSuiGas": "Sui Gas", + "transFiber": "Fiber", + "transMinerva": "Minerva", + "transNestle": "transNestle", + "transAquaFujitenma": "transAquaFujitenma", + "transZong": "Zong", + "transPepsiCo": "transPepsiCo", + "textLeave20": "20", + "textLeaves": "Leaves", + "textGet": "Get", + "textLeave100": "100", + "textLeave50": "50", + "textChange": "Change", + "textDeliveryAddress": "Delivery Address", + "textChequeBookRequestAddress": "Level-1, Block-A, STP-Software Technology Park, Service Road North, I – 9/3 Islamabad, Pakistan", + "textCharges": "Charges", + "textScheduleCharges": "As per schedule of the charges", + "textDate": "Date", + "textDateContent": "Dec 20, 2023", + "textRequestSummary": "Request Summary", + "textPurpose": "Purpose", + "textNumberofLeaves": "Number of Leaves", + "textChequeRequestTitle": "Cheque Request", + "textQueryContent": "Your cheque book will be delivered within 7 working days. For inquiries, call us at 111-825-888 or send us an email with your registered email address at customer.services@ubl.com.pk", + "textDeposit": "Deposit", + "textChequeDeposit": "Cheque Deposit", + "textChequeStatusContent": "Enter the cheque number to check its status", + "textDepositToChequing": "Deposit To Chequing", + "text1000": "\n\$1000", + "textMax300000": "Max:300000", + "textSelectAccount": "Select Account", + "textFrontOfCheque": "Front Of Cheque", + "textTryAgain": "Try Again", + "textChequeStatus": "Cheque Status", + "textChequeActivation": "Cheque Activation", + "textChequeRequest": "Cheque Request", + "textChequeRequestContent": "Please select the cheque book with leaves", + "textChequeStatusHistory": "Cheque Status History", + "textChequeStatusHistoryContent": "Enter the cheque number to check its status", + "textChequeStatusCheckNumber": "Check # xxxxxxx9083", + "textChequeStatusHistoryRefNo": "ref #IBE5BH8976CF", + "textChequeStatusHistorySuccess": "Success", + "textChequeStatusHistoryCancel": "Cancel", + "textPTCLLandLine": "PTCL Land Line", + "textSelectAccountDetails": "Select Account Details", + "textCreditCard": "Credit Card", + "textCreditCardNumber": "4025***********8892", + "textAmountDebit": "Amount Debit", + "textEnterConsumerName": "Enter Consumer Name", + "textTotalAmount": "Total Amount", + "textEnterAmount": "Enter Amount", + "textBillDetails": "Bill Details", + "textBillConsumerName": "Consumer Name", + "textBillAmount": "Bill Amount", + "textDueDate": "Due Date", + "textAmountDueAfterDueDate": "Amount Due After Due Date", + "textBillStatus": "Bill Status", + "textBillDetailZero": "0", + "textBillDetailDate": "02/19/24", + "textBillDetailUnPaid": "UnPaid", + "textPayNow": "Pay Now", + "textBillDetailContent": "Your Electricity Land Line bill is", + "textBillDetailBalance": "PKR 12394", + "textBillDetailBillAmount": "Amount", + "textBillDetailBillDueDate": "Due Date", + "textBillDetailBillAmountDue": "Amount Due", + "textBillDetailBillAfterDueDate": "After Due Date", + "textBillDetailBillStatus": "Bill Status", + "textProfileHey": "Hey,", + "textProfileUsername": "Username", + "textAppSettingTitle": "App Setting", + "textLanguagesTitle": "Languages", + "textDarkModeContent": "Tap to change your Theme Mode", + "textFingerPrintTitle": "FingerPrint", + "textFingerPrintContent": "Tap to unlock Fingerprint", + "textPasswordChangeTitle": "Change Password", + "textPasswordChangeContent": "Tap to change your Password", + "textTermOfService": "Term of Service", + "textPrivacy": "Privacy", + "textInviteFriends": "Invite Friends", + "textDialogConformation": "Conformation", + "textDialogContent": "Are you sure you want to log out?", + "textSignOut": "SignOut", + "textSearch": "Search...", + "textSelectYourOption": "Select Your Option", + "textLanguageEnglish": "English", + "textLanguageArabic": "Arabic", + "textLanguageUrdu": "Urdu", + "textNoSelect": "No Selection", + "textMyAccountTitle": "My Account", + "textMyAccountAccountTitle": "Account Title", + "textMyAccountAccountNumber": "Account Number", + "textMyAccountBranchCode": "Branch Code", + "textMyAccountAccountOpeningDate": "Account Opening Date", + "textAppSetting": "App Setting", + "textLoginTitle": "Login", + "textInvalidFingerprint": "Record not against your finger print, please login with credentials", + "textPasswordPattern": "Password requires: 8 + characters, upper/lower case letters, number, special character.", + "textDailyTransactionLimit": "Daily Transaction Limit", + "textChangeTransactionPin": "Change Pin", + "textQRSetting": "QR Setting", + "textTransactionLimit": "Transaction Limit", + "textTransactionPin": "Transaction Pin", + "textOldLimit": "Rs.1,000,000", + "textMaximumLengthContent": "The maximum limit that can be set is Rs. 10 million", + "textLimitNoteContent": "Note: If you do not have a Debit card, please call the contact center or send us an email at customer.", + "textCurrentDailyLimit": "Current Daily Limit", + "textDone": "Done", + "textPinOTPMessage": "Your Transaction Pin OTP has been Successfully updated! An update email and message has been sent to you.", + "textYourUCOQR": "Your UCO QR", + "textUCOQRContent": "Share this QR Code with sender or they can scan it from your phone to receive money through UCO", + "textQrAccountName": "Muhammad Bilal", + "textQrAccountNumber": "MSISDN: ********** 2222", + "textShareQRCode": "Share QR Code", + "textSavetoGallery": "Save to Gallery", + "textNotifications": "Notifications", + "textFilter": "Filter", + "textChequeNumber": "Cheque Number", + "textCreateTransactionPin": "Create Transaction Pin", + "textShare": "Share", + "textPleaseCreatenewtransactionpin": "Please Create a New Transaction Pin", + "textConfirmTransactionPin": "Please Confirm New Transaction Pin", + "textOldTransactionPin": "Please old Transaction Pin", + "textNotificationDetails": "Notification Details", + "textNotificationDetailsContent": "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account 03273653107. Fee: Rs. 0.0. Trx ID 27586324598.", + "textError": "Error!!", + "textDescription": "Something happened wrong! Please check it.", + "textInform": "Information!!", + "Continue": "Continue", + "textConfirmTransaction": "Confirm Transaction", + "textHowdoyouwanttopay": "How do you want to pay", + "textDebitCard": "Debit Card", + "textDebitCardContent": "10.78 GBP fee, so recipient gets 340839.71 PKR.Should arrive in seconds", + "textBankTransfer": "Bank Transfer", + "textGeneralLedger": "General Ledger", + "transAddMoney": "Add Money", + "textGLCode": "GL Code", + "textFaqs": "FAQ'S", + "textHowCanIHelpYou": "Hi, how can we help?", + "textExploreAllArticles": "Explore all topics", + "textFirstName": "First Name", + "textLastName": "Last Name", + "textBackofCheque": "Back of Cheque", + "textEnterEmail": "Email Address", + "textOurFee": "Our Fee", + "textTotalAmountWellConvert": "Total Amount We'll Convert", + "textGuaranteedExchnageRate": "Guaranteed Exchange Rate", + "textSelectYourGLSAccount": "Select Your GLS Account", + "textGlsAccounts": "Gls Accounts", + "textEnterMessage": "Enter Message", + "textWarningContent": "Are you sure you want to delete this Beneficiary.", + "textAddBeneficiary": "Add Beneficiary", + + // /// Double keys + // "textWHODescription": + // "The UCO team members are experienced and tested executives capable of executing this impact oriented initiative of global magnitude. We have decades of expertise in financial and mobile technology, cybercrime prevention, security, compliance, consumer goods, marketing, and advertising. We are also backed by advisors who are former Fortune 50 chief officers in the areas of: technology, banking, and finance.", + // "textApply": "Apply", + // "textJobTitle": "Senior ui/ux designer", + // "textOfficeAddress": "Islamabad, Pakistan", + // "textJobSkills": "Photoshop, Adobe XD,Invision, Figma", + // "textSelectPersonalAccount": "Select Personal Account", + // "textRecipientDetail": "Recipient Detail", + // "textPhoneNumber": "Phone Number", + // "textRecipientCardName": "Recipient CardName", + // "textSelectCurrency": "Select Currency", + // "textSendingAmount": "Sending Amount", + // "textExchangeRate": "Exchange Rate", + // "textMessageMemo": "Message/Memo", + // "textSend": "Send", + // "textClear": "Clear", + // "textPermissionDenied": "Permission Denied", + // "textMyProfile": "My Profile", + // "textNotFound": "Not Found", + // "textRecipient": "Recipient", + // "textHome": "Home", + // "textCurrency": "Currency", + // "textMessage": "Message", + // "textConfirm": "Confirm", + // "textEndingBalance": "Ending Balance", + // "textPendingRemittance": "Pending Remittance", + // "textReceived": "Received", + // "textPinCode": "Pin Code", + // "textBack": "Back", + // "textCancelDescription": "Are you Sure you want to Cancel", + // "textYes": "Yes", + "textErrorRequired": "This field is required", + "textPay": "Pay", + "textDelete": "Delete", + "textAddToBeneficiary": "Add To Beneficiary", + "textTransferAmount": "Transfer Amount", + }, + }; +} diff --git a/lib/app/models/AccountInquiryResponseModel.dart b/lib/app/models/AccountInquiryResponseModel.dart new file mode 100644 index 0000000..49c9263 --- /dev/null +++ b/lib/app/models/AccountInquiryResponseModel.dart @@ -0,0 +1,44 @@ +class AccountInquiryResponseModel { + String mbmBkmstitle = ""; + String mbmBkmsnumber = ""; + String pcrCurrcode = ""; + String pcrCurrdesc = ""; + String pcrCurrshort = ""; + + AccountInquiryResponseModel({ + this.mbmBkmstitle = "", + this.mbmBkmsnumber = "", + this.pcrCurrcode = "", + this.pcrCurrdesc = "", + this.pcrCurrshort = "", + }); + + static List fromList(List list) { + return list.map((item) => AccountInquiryResponseModel.fromMap(AccountInquiryResponseModel.fromMap(item as Map).toMap())).toList(); + } + + Map toMap() { + return { + 'mbmBkmstitle': this.mbmBkmstitle, + 'mbmBkmsnumber': this.mbmBkmsnumber, + 'pcrCurrcode': this.pcrCurrcode, + 'pcrCurrdesc': this.pcrCurrdesc, + 'pcrCurrshort': this.pcrCurrshort, + }; + } + + factory AccountInquiryResponseModel.fromMap(Map map) { + return AccountInquiryResponseModel( + mbmBkmstitle: map['mbmBkmstitle'] ?? "", + mbmBkmsnumber: map['mbmBkmsnumber'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + ); + } + + @override + String toString() { + return 'AccountInquiryResponseModel{mbmBkmstitle: $mbmBkmstitle, mbmBkmsnumber: $mbmBkmsnumber, pcrCurrcode: $pcrCurrcode, pcrCurrdesc: $pcrCurrdesc, pcrCurrshort: $pcrCurrshort}'; + } +} diff --git a/lib/app/models/AddNewAccountRequestModel.dart b/lib/app/models/AddNewAccountRequestModel.dart new file mode 100644 index 0000000..aaf0504 --- /dev/null +++ b/lib/app/models/AddNewAccountRequestModel.dart @@ -0,0 +1,34 @@ +class AddNewAccountRequestModel { + String porOrgacode = ""; + String email = ""; + String title = ""; + String dmpProdcode = ""; + String channelCode = ""; + + AddNewAccountRequestModel({this.porOrgacode = "", this.email = "", this.title = "", this.dmpProdcode = "", this.channelCode = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'email': this.email, + 'title': this.title, + 'dmpProdcode': this.dmpProdcode, + 'channelCode': this.channelCode, + }; + } + + factory AddNewAccountRequestModel.fromMap(Map map) { + return AddNewAccountRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + email: map['email'] ?? "", + title: map['title'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + channelCode: map['channelCode'] ?? "", + ); + } + + @override + String toString() { + return 'AddNewAccountRequestModel{porOrgacode: $porOrgacode, email: $email, title: $title, dmpProdcode: $dmpProdcode, channelCode: $channelCode}'; + } +} diff --git a/lib/app/models/AuthenticationRequest.dart b/lib/app/models/AuthenticationRequest.dart new file mode 100644 index 0000000..988f497 --- /dev/null +++ b/lib/app/models/AuthenticationRequest.dart @@ -0,0 +1,47 @@ +class AuthenticationRequest { + String email = ""; + String password = ""; + bool isOtpRequired = false; + String porOrgacode = ""; + String channelCode = ""; + + AuthenticationRequest.empty() + : this.email = "", + this.password = "", + this.isOtpRequired = false, + this.porOrgacode = "", + this.channelCode = ""; + + AuthenticationRequest({ + this.email = "", + this.password = "", + this.isOtpRequired = false, + this.porOrgacode = "", + this.channelCode = "", + }); + + Map toMap() { + return { + 'email': email, + 'password': password, + 'isOtpRequired': isOtpRequired, + 'porOrgacode': porOrgacode, + 'channelCode': channelCode, + }; + } + + factory AuthenticationRequest.fromMap(Map map) { + return AuthenticationRequest( + email: map['email'], + password: map['password'], + isOtpRequired: map['isOtpRequired'], + porOrgacode: map['porOrgacode'], + channelCode: map['channelCode'], + ); + } + + @override + String toString() { + return 'AuthenticationRequest{email: $email, password: $password, isOtpRequired: $isOtpRequired, porOrgacode: $porOrgacode, channelCode: $channelCode}'; + } +} diff --git a/lib/app/models/AuthenticationResponse.dart b/lib/app/models/AuthenticationResponse.dart new file mode 100644 index 0000000..3423c09 --- /dev/null +++ b/lib/app/models/AuthenticationResponse.dart @@ -0,0 +1,52 @@ +class AuthenticationResponse { + String name = ""; + String cmpCuststatus = ""; + String cmpCustlastlogin = ""; + String cmpCustcode = ""; + // Role userRole = ""; + String jwtToken = ""; + String refreshToken = ""; + bool isKycVerified = false; + + AuthenticationResponse({ + this.name = "", + this.cmpCuststatus = "", + this.cmpCustlastlogin = "", + this.cmpCustcode = "", + //this.userRole = "", + this.jwtToken = "", + this.refreshToken = "", + this.isKycVerified = false, + }); + + Map toMap() { + return { + 'name': name, + 'cmpCuststatus': cmpCuststatus, + 'cmpCustlastlogin': cmpCustlastlogin, + 'cmpCustcode': cmpCustcode, + //'userRole': userRole.toMap(), // Assuming Role has a toMap method + 'jwtToken': jwtToken, + 'refreshToken': refreshToken, + 'isKycVerified': isKycVerified, + }; + } + + factory AuthenticationResponse.fromMap(Map map) { + return AuthenticationResponse( + name: map['name'] ?? "", + cmpCuststatus: map['cmpCuststatus'] ?? "", + cmpCustlastlogin: map['cmpCustlastlogin'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + // userRole: Role.fromMap(map['userRole']), // Assuming Role has a fromMap method + jwtToken: map['jwtToken'] ?? "", + refreshToken: map['refreshToken'] ?? "", + isKycVerified: map['isKycVerified'] ?? "", + ); + } + + @override + String toString() { + return 'AuthenticationResponse{name: $name, cmpCuststatus: $cmpCuststatus, cmpCustlastlogin: $cmpCustlastlogin, cmpCustcode: $cmpCustcode, /*userRole: userRole,*/ jwtToken: $jwtToken, refreshToken: $refreshToken, isKycVerified: $isKycVerified}'; + } +} diff --git a/lib/app/models/BeneficiaryAccountModel.dart b/lib/app/models/BeneficiaryAccountModel.dart new file mode 100644 index 0000000..dbba4f6 --- /dev/null +++ b/lib/app/models/BeneficiaryAccountModel.dart @@ -0,0 +1,61 @@ +class BeneficiaryAccountModel { + String porOrgacode = ""; + String email = ""; + String pcrCurrcode = ""; + String pcrCurrdesc = ""; + String pcrCurrshort = ""; + String mbmBkmstitleRef = ""; + String mbmBkmsnumberRef = ""; + String refPhoneNumber = ""; + String refEmail = ""; + String refNickName = ""; + + + BeneficiaryAccountModel({ + this.porOrgacode = "", + this.email = "", + this.pcrCurrcode = "", + this.pcrCurrdesc = "", + this.pcrCurrshort = "", + this.mbmBkmstitleRef = "", + this.mbmBkmsnumberRef = "", + this.refPhoneNumber = "", + this.refEmail = "", + this.refNickName = "", + }); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'email': this.email, + 'pcrCurrcode': this.pcrCurrcode, + 'pcrCurrdesc': this.pcrCurrdesc, + 'pcrCurrshort': this.pcrCurrshort, + 'mbmBkmstitleRef': this.mbmBkmstitleRef, + 'mbmBkmsnumberRef': this.mbmBkmsnumberRef, + 'refPhoneNumber': this.refPhoneNumber, + 'refEmail': this.refEmail, + 'refNickName': this.refNickName, + }; + } + + factory BeneficiaryAccountModel.fromMap(Map map) { + return BeneficiaryAccountModel( + porOrgacode: map['porOrgacode'] ?? "", + email: map['email'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + mbmBkmstitleRef: map['mbmBkmstitleRef'] ?? "", + mbmBkmsnumberRef: map['mbmBkmsnumberRef'] ?? "", + refPhoneNumber: map['refPhoneNumber'] ?? "", + refEmail: map['refEmail'] ?? "", + refNickName: map['refNickName'] ?? "", + ); + } + + @override + String toString() { + return 'BeneficiaryAccountModel{porOrgacode: $porOrgacode, email: $email, pcrCurrcode: $pcrCurrcode, pcrCurrdesc: $pcrCurrdesc, pcrCurrshort: $pcrCurrshort, mbmBkmstitleRef: $mbmBkmstitleRef, mbmBkmsnumberRef: $mbmBkmsnumberRef, refPhoneNumber: $refPhoneNumber, refEmail: $refEmail, refNickName: $refNickName}'; + } +} diff --git a/lib/app/models/Branch.dart b/lib/app/models/Branch.dart new file mode 100644 index 0000000..768a3a4 --- /dev/null +++ b/lib/app/models/Branch.dart @@ -0,0 +1,15 @@ +class Branch { + final String name; + final double latitude; + final double longitude; + final String contactNumber; + final String address; + + Branch({ + required this.name, + required this.latitude, + required this.longitude, + required this.contactNumber, + required this.address, + }); +} \ No newline at end of file diff --git a/lib/app/models/ChangePasswordRequest.dart b/lib/app/models/ChangePasswordRequest.dart new file mode 100644 index 0000000..d336afc --- /dev/null +++ b/lib/app/models/ChangePasswordRequest.dart @@ -0,0 +1,32 @@ +class ChangePasswordRequest { + String oldPassword = ""; + String newPassword = ""; + String email = ""; + + ChangePasswordRequest({ + this.oldPassword = "", + this.newPassword = "", + this.email = "", + }); + + Map toMap() { + return { + 'oldPassword': oldPassword, + 'newPassword': newPassword, + 'email': email, + }; + } + + factory ChangePasswordRequest.fromMap(Map map) { + return ChangePasswordRequest( + oldPassword: map['oldPassword'], + newPassword: map['newPassword'], + email: map['email'], + ); + } + + @override + String toString() { + return 'ChangePasswordRequest{oldPassword: $oldPassword, newPassword: $newPassword, email: $email}'; + } +} diff --git a/lib/app/models/ChangeTransactionPinRequest.dart b/lib/app/models/ChangeTransactionPinRequest.dart new file mode 100644 index 0000000..c596dba --- /dev/null +++ b/lib/app/models/ChangeTransactionPinRequest.dart @@ -0,0 +1,64 @@ +class ChangeTransactionPinRequest { + String oldTransPincode = ""; + String newTransPincode = ""; + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + bool isOtpRequired = false; + String pinType = ""; + + ChangeTransactionPinRequest({ + this.oldTransPincode = "", + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequired = false, + this.pinType = "", + }); + + ChangeTransactionPinRequest.empty() + : this.oldTransPincode = "", + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequired = false, + this.pinType = ""; + + // Convert object to a Map + Map toMap() { + return { + 'oldTransPincode': oldTransPincode, + 'newTransPincode': newTransPincode, + 'channelCode': channelCode, + 'pctCstycode': pctCstycode, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'isOtpRequire': isOtpRequired, + 'pinType': pinType, + }; + } + + // Create object from a Map + factory ChangeTransactionPinRequest.fromMap(Map map) { + return ChangeTransactionPinRequest( + oldTransPincode: map['oldTransPincode'] ?? '' , + newTransPincode: map['newTransPincode'] ?? '', + channelCode: map['channelCode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + isOtpRequired: map['isOtpRequire'] ?? '', + pinType: map['pinType'], + ); + } + + @override + String toString() { + return 'ChangeTransactionPinRequest{oldTransPincode: $oldTransPincode, newTransPincode: $newTransPincode, channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, isOtpRequired: $isOtpRequired, pinType: $pinType}'; + } +} diff --git a/lib/app/models/CreateTransactionPinOTPRequest.dart b/lib/app/models/CreateTransactionPinOTPRequest.dart new file mode 100644 index 0000000..c8a1c11 --- /dev/null +++ b/lib/app/models/CreateTransactionPinOTPRequest.dart @@ -0,0 +1,57 @@ +class CreateTransactionPinOTPRequest { + String newTransPincode = ""; + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + bool isOtpRequire = false; + String pinType = ""; + + CreateTransactionPinOTPRequest({ + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequire = false, + this.pinType = "", + }); + + CreateTransactionPinOTPRequest.empty() + : this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequire = false, + this.pinType = ""; + + Map toMap() { + return { + 'newTransPincode': newTransPincode, + 'channelCode': channelCode, + 'pctCstycode': pctCstycode, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'isOtpRequire': isOtpRequire, + 'pinType': pinType, + }; + } + + factory CreateTransactionPinOTPRequest.fromMap(Map map) { + return CreateTransactionPinOTPRequest( + newTransPincode: map['newTransPincode'], + channelCode: map['channelCode'], + pctCstycode: map['pctCstycode'], + porOrgacode: map['porOrgacode'], + cmpCustcode: map['cmpCustcode'], + isOtpRequire: map['isOtpRequire'], + pinType: map['pinType'], + ); + } + + @override + String toString() { + return 'CreateTransactionPinOTPRequest{newTransPincode: $newTransPincode, channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, isOtpRequire: $isOtpRequire, pinType: $pinType}'; + } +} diff --git a/lib/app/models/CreateTransactionPinRequest.dart b/lib/app/models/CreateTransactionPinRequest.dart new file mode 100644 index 0000000..14a26e0 --- /dev/null +++ b/lib/app/models/CreateTransactionPinRequest.dart @@ -0,0 +1,49 @@ +class CreateTransactionPinRequest { + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + String email = ""; + String obpPincode = ""; + String pinType = ""; + + + CreateTransactionPinRequest({ + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.email = "", + this.obpPincode = "", + this.pinType = "", + }); + + Map toMap() { + return { + 'channelCode': this.channelCode, + 'pctCstycode': this.pctCstycode, + 'porOrgacode': this.porOrgacode, + 'cmpCustcode': this.cmpCustcode, + 'email': this.email, + 'obpPincode': this.obpPincode, + 'pinType': this.pinType, + }; + } + + factory CreateTransactionPinRequest.fromMap(Map map) { + return CreateTransactionPinRequest( + channelCode: map['channelCode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + email: map['email'] ?? "", + obpPincode: map['obpPincode'] ?? "", + pinType: map['pinType'] ?? "", + ); + } + + @override + String toString() { + return 'CreateTransactionPinRequest{channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, email: $email, obpPincode: $obpPincode, pinType: $pinType}'; + } +} diff --git a/lib/app/models/DepositAccountResponse.dart b/lib/app/models/DepositAccountResponse.dart new file mode 100644 index 0000000..7ae8089 --- /dev/null +++ b/lib/app/models/DepositAccountResponse.dart @@ -0,0 +1,152 @@ +class DepositAccount { + String porOrgacode = ""; + String mbmBkmsnumber = ""; + String pcrCurrdesc = ""; + String pctCstycode = ""; + String mbmBkmstitle = ""; + double mbmBkmsbalance = 0.0; + String mbmBkmsopendate = ""; + String accountType = ""; + String transactionLimit = ""; + String dmpProddesc = ""; + String plcLocadesc = ""; + String pcrCurrcode = ""; + String cmpCustcode = ""; + String dmpProdcode = ""; + String plcLocacode = ""; + String padAdrsmobphone = ""; + String pasAcstcode = ""; + String pcrCurrshort = ""; + + + DepositAccount({ + this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.pcrCurrdesc = "", + this.pctCstycode = "", + this.mbmBkmstitle = "", + this.mbmBkmsbalance = 0.0, + this.mbmBkmsopendate = "", + this.accountType = "", + this.transactionLimit = "", + this.dmpProddesc = "", + this.plcLocadesc = "", + this.pcrCurrcode = "", + this.cmpCustcode = "", + this.dmpProdcode = "", + this.plcLocacode = "", + this.padAdrsmobphone = "", + this.pasAcstcode = "", + this.pcrCurrshort = "", + }); + + DepositAccount.empty() + : this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.pcrCurrdesc = "", + this.pctCstycode = "", + this.mbmBkmstitle = "", + this.mbmBkmsbalance = 0.0, + this.mbmBkmsopendate = "", + this.accountType = "", + this.transactionLimit = "", + this.dmpProddesc = "", + this.plcLocadesc = "", + this.pcrCurrcode = "", + this.cmpCustcode = "", + this.dmpProdcode = "", + this.plcLocacode = "", + this.padAdrsmobphone = "", + this.pasAcstcode = "", + this.pcrCurrshort = ""; + + factory DepositAccount.fromMap(Map map) { + return DepositAccount( + porOrgacode: map['porOrgacode'] ?? "", + mbmBkmsnumber: map['mbmBkmsnumber'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + mbmBkmstitle: map['mbmBkmstitle'] ?? "", + mbmBkmsbalance: (map['mbmBkmsbalance'] ?? 0.0).toDouble(), + mbmBkmsopendate: map['mbmBkmsopendate'] ?? "", + accountType: map['accountType'] ?? "", + transactionLimit: map['transactionLimit'] ?? "", + dmpProddesc: map['dmpProddesc'] ?? "", + plcLocadesc: map['plcLocadesc'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + plcLocacode: map['plcLocacode'] ?? "", + padAdrsmobphone: map['padAdrsmobphone'] ?? "", + pasAcstcode: map['pasAcstcode'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + ); + } + + Map toMap() { + final Map data = { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'pcrCurrdesc': pcrCurrdesc, + 'pctCstycode': pctCstycode, + 'mbmBkmstitle': mbmBkmstitle, + 'mbmBkmsbalance': mbmBkmsbalance, + 'mbmBkmsopendate': mbmBkmsopendate, + 'accountType': accountType, + 'transactionLimit': transactionLimit, + 'dmpProddesc': dmpProddesc, + 'plcLocadesc': plcLocadesc, + 'pcrCurrcode': pcrCurrcode, + 'cmpCustcode': cmpCustcode, + 'dmpProdcode': dmpProdcode, + 'plcLocacode': plcLocacode, + 'padAdrsmobphone': padAdrsmobphone, + 'pasAcstcode': pasAcstcode, + 'pcrCurrshort': pcrCurrshort, + }; + return data; + } + + DepositAccount copyWith({ + String? porOrgacode, + String? mbmBkmsnumber, + String? pcrCurrdesc, + String? pcrCurrCode, + String? pctCstycode, + String? mbmBkmstitle, + double? mbmBkmsbalance, + String? mbmBkmsopendate, + String? accountType, + String? transactionLimit, + String? dmpProddesc, + String? plcLocadesc, + String? pcrCurrcode, + String? cmpCustcode, + String? dmpProdcode, + String? plcLocacode, + String? padAdrsmobphone, + String? pasAcstcode, + String? pcrCurrshort, + }) { + return DepositAccount( + porOrgacode: porOrgacode ?? this.porOrgacode, + mbmBkmsnumber: mbmBkmsnumber ?? this.mbmBkmsnumber, + pcrCurrdesc: pcrCurrdesc ?? this.pcrCurrdesc, + pctCstycode: pctCstycode ?? this.pctCstycode, + mbmBkmstitle: mbmBkmstitle ?? this.mbmBkmstitle, + mbmBkmsbalance: mbmBkmsbalance ?? this.mbmBkmsbalance, + mbmBkmsopendate: mbmBkmsopendate ?? this.mbmBkmsopendate, + accountType: accountType ?? this.accountType, + transactionLimit: transactionLimit ?? this.transactionLimit, + dmpProddesc: dmpProddesc ?? this.dmpProddesc, + plcLocadesc: plcLocadesc ?? this.plcLocadesc, + pcrCurrcode: pcrCurrcode ?? this.pcrCurrcode, + cmpCustcode: cmpCustcode ?? this.cmpCustcode, + dmpProdcode: dmpProdcode ?? this.dmpProdcode, + plcLocacode: plcLocacode ?? this.plcLocacode, + padAdrsmobphone: padAdrsmobphone ?? this.padAdrsmobphone, + pasAcstcode: pasAcstcode ?? this.pasAcstcode, + pcrCurrshort: pcrCurrshort ?? this.pcrCurrshort, + ); + } +} diff --git a/lib/app/models/DepositAccountTransaction.dart b/lib/app/models/DepositAccountTransaction.dart new file mode 100644 index 0000000..17749d9 --- /dev/null +++ b/lib/app/models/DepositAccountTransaction.dart @@ -0,0 +1,61 @@ +class DepositAccountTransaction { + String tranID = ""; + String sgtGntrCreatedAt = ""; + String sgtGntrNarration = ""; + String sgtGntrvaluedate = ""; + String deposit = ""; + String withdrawal = ""; + String status = ""; + String sgtGntramt = ""; + + DepositAccountTransaction({ + this.tranID = "", + this.sgtGntrCreatedAt = "", + this.sgtGntrNarration = "", + this.sgtGntrvaluedate = "", + this.deposit = "", + this.withdrawal = "", + this.status = "", + this.sgtGntramt = "", + }); + + Map toMap() { + return { + 'tranID': tranID, + 'sgtGntrCreatedAt': sgtGntrCreatedAt, + 'sgtGntrNarration': sgtGntrNarration, + 'sgtGntrvaluedate': sgtGntrvaluedate, + 'deposit': deposit, + 'withdrawal': withdrawal, + 'status': status, + 'sgtGntramt': sgtGntramt, + }; + } + + factory DepositAccountTransaction.fromMap(Map map) { + return DepositAccountTransaction( + tranID: map['tranID'] ?? '', + sgtGntrCreatedAt: map['sgtGntrCreatedAt'] ?? '', + sgtGntrNarration: map['sgtGntrNarration'] ?? '', + sgtGntrvaluedate: map['sgtGntrvaluedate'] ?? '', + deposit: map['deposit'] ?? '', + withdrawal: map['withdrawal'] ?? '', + status: map['status'] ?? '', + sgtGntramt: map['sgtGntramt'] ?? '', + ); + } + + @override + String toString() { + return 'DepositAccountTransaction{' + 'tranID: $tranID, ' + 'sgtGntrCreatedAt: $sgtGntrCreatedAt, ' + 'sgtGntrNarration: $sgtGntrNarration, ' + 'sgtGntrvaluedate: $sgtGntrvaluedate, ' + 'deposit: $deposit, ' + 'withdrawal: $withdrawal, ' + 'status: $status, ' + 'sgtGntramt: $sgtGntramt' + '}'; + } +} diff --git a/lib/app/models/ExchangeRate.dart b/lib/app/models/ExchangeRate.dart new file mode 100644 index 0000000..abcea4e --- /dev/null +++ b/lib/app/models/ExchangeRate.dart @@ -0,0 +1,67 @@ +class ExchangeRate { + String petExrtdesc = ""; + String pcrCurrcode = ""; + double perEratrateact = 0.0; + String petExrtcode = ""; + String perEratdate = ""; + String pcrCurrshort = ""; + String porOrgacode = ""; + String pcrCurrdesc = ""; + bool pcrCurrbase = false; + + ExchangeRate({ + this.petExrtdesc = "", + this.pcrCurrcode = "", + this.perEratrateact = 0.0, + this.petExrtcode = "", + this.perEratdate = "", + this.pcrCurrshort = "", + this.porOrgacode = "", + this.pcrCurrdesc = "", + this.pcrCurrbase = false, + }); + + ExchangeRate.empty() + : this.petExrtdesc = "", + this.pcrCurrcode = "", + this.perEratrateact = 0.0, + this.petExrtcode = "", + this.perEratdate = "", + this.pcrCurrshort = "", + this.porOrgacode = "", + this.pcrCurrdesc = "", + this.pcrCurrbase = false; + + factory ExchangeRate.fromMap(Map json) { + return ExchangeRate( + petExrtdesc: json['petExrtdesc'] ?? "", + pcrCurrcode: json['pcrCurrcode'] ?? "", + perEratrateact: json['perEratrateact'] ?? 0.0, + petExrtcode: json['petExrtcode'] ?? "", + perEratdate: json['perEratdate'] ?? "", + pcrCurrshort: json['pcrCurrshort'] ?? "", + porOrgacode: json['porOrgacode'] ?? "", + pcrCurrdesc: json['pcrCurrdesc'] ?? "", + pcrCurrbase: json['pcrCurrbase'] ?? false, + ); + } + + Map toMap() { + return { + 'petExrtdesc': petExrtdesc, + 'pcrCurrcode': pcrCurrcode, + 'perEratrateact': perEratrateact, + 'petExrtcode': petExrtcode, + 'perEratdate': perEratdate, + 'pcrCurrshort': pcrCurrshort, + 'porOrgacode': porOrgacode, + 'pcrCurrdesc': pcrCurrdesc, + 'pcrCurrbase': pcrCurrbase, + }; + } + + @override + String toString() { + return 'ExchangeRate{petExrtdesc: $petExrtdesc, pcrCurrcode: $pcrCurrcode, perEratrateact: $perEratrateact, petExrtcode: $petExrtcode, perEratdate: $perEratdate, pcrCurrshort: $pcrCurrshort, porOrgacode: $porOrgacode, pcrCurrdesc: $pcrCurrdesc, pcrCurrbase: $pcrCurrbase}'; + } +} diff --git a/lib/app/models/GLACCAddMoneyRequestModel.dart b/lib/app/models/GLACCAddMoneyRequestModel.dart new file mode 100644 index 0000000..ee7d1e1 --- /dev/null +++ b/lib/app/models/GLACCAddMoneyRequestModel.dart @@ -0,0 +1,122 @@ +class GLACCAddMoneyRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String drPcaGlaccode = ""; + String drPcaGlacdesc = ""; + String crMbmBkmsnumber = ""; + String crMbmBkmstitle = ""; + String crPcrCurrcode = ""; + String crPcrCurrdesc = ""; + String crPcrCurrshort = ""; + String sgtGntrnarration = ""; + String dmpProdCode = ""; + String transType = ""; + String notificationId = ""; + String transMode = ""; + double sgtGntramtfc = 0.0; + String otdTrancomment = ""; + String obpPincode = ""; + String pinType = ""; + + GLACCAddMoneyRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drPcaGlaccode = "", + this.drPcaGlacdesc = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0.0, + this.otdTrancomment = "", + this.obpPincode = "", + this.pinType = "", + }); + + GLACCAddMoneyRequestModel.empty() + : this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drPcaGlaccode = "", + this.drPcaGlacdesc = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0.0, + this.otdTrancomment = "", + this.obpPincode = "", + this.pinType = ""; + + @override + String toString() { + return 'GLACCAddMoneyRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, drPcaGlaccode: $drPcaGlaccode, drPcaGlacdesc: $drPcaGlacdesc, crMbmBkmsnumber: $crMbmBkmsnumber, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrcode: $crPcrCurrcode, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrshort: $crPcrCurrshort, sgtGntrnarration: $sgtGntrnarration, dmpProdCode: $dmpProdCode, transType: $transType, notificationId: $notificationId, transMode: $transMode, sgtGntramtfc: $sgtGntramtfc, otdTrancomment: $otdTrancomment, obpPincode: $obpPincode, pinType: $pinType}'; + } + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'pctCstycode': this.pctCstycode, + 'channelCode': this.channelCode, + 'cmpCustcode': this.cmpCustcode, + 'drPcaGlaccode': this.drPcaGlaccode, + 'drPcaGlacdesc': this.drPcaGlacdesc, + 'crMbmBkmsnumber': this.crMbmBkmsnumber, + 'crMbmBkmstitle': this.crMbmBkmstitle, + 'crPcrCurrcode': this.crPcrCurrcode, + 'crPcrCurrdesc': this.crPcrCurrdesc, + 'crPcrCurrshort': this.crPcrCurrshort, + 'sgtGntrnarration': this.sgtGntrnarration, + 'dmpProdCode': this.dmpProdCode, + 'transType': this.transType, + 'notificationId': this.notificationId, + 'transMode': this.transMode, + 'sgtGntramtfc': this.sgtGntramtfc, + 'otdTrancomment': this.otdTrancomment, + 'obpPincode': this.obpPincode, + 'pinType': this.pinType, + }; + } + + factory GLACCAddMoneyRequestModel.fromMap(Map map) { + return GLACCAddMoneyRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + drPcaGlaccode: map['drPcaGlaccode'] ?? "", + drPcaGlacdesc: map['drPcaGlacdesc'] ?? "", + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + sgtGntrnarration: map['sgtGntrnarration'] ?? "", + dmpProdCode: map['dmpProdCode'] ?? "", + transType: map['transType'] ?? "", + notificationId: map['notificationId'] ?? "", + transMode: map['transMode'] ?? "", + sgtGntramtfc: map['sgtGntramtfc'] ?? 0.0, + otdTrancomment: map['otdTrancomment'] ?? "", + obpPincode: map['obpPincode'] ?? "", + pinType: map['pinType'] ?? "", + ); + } +} diff --git a/lib/app/models/GenerateReportRequestModel.dart b/lib/app/models/GenerateReportRequestModel.dart new file mode 100644 index 0000000..2568e14 --- /dev/null +++ b/lib/app/models/GenerateReportRequestModel.dart @@ -0,0 +1,40 @@ +class GenerateReportRequestModel { + final String porOrgacode; + final String mbmBkmsnumber; + final String sgtGntrvaluedatefrom; + final String sgtGntrvaluedateto; + final String type; + + GenerateReportRequestModel({ + required this.porOrgacode, + required this.mbmBkmsnumber, + required this.sgtGntrvaluedatefrom, + required this.sgtGntrvaluedateto, + required this.type, + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'sgtGntrvaluedatefrom': sgtGntrvaluedatefrom, + 'sgtGntrvaluedateto': sgtGntrvaluedateto, + 'type': type, + }; + } + + factory GenerateReportRequestModel.fromMap(Map map) { + return GenerateReportRequestModel( + porOrgacode: map['porOrgacode'], + mbmBkmsnumber: map['mbmBkmsnumber'], + sgtGntrvaluedatefrom: map['sgtGntrvaluedatefrom'], + sgtGntrvaluedateto: map['sgtGntrvaluedateto'], + type: map['type'], + ); + } + + @override + String toString() { + return 'TransactionHistoryRequest{porOrgacode: $porOrgacode, mbmBkmsnumber: $mbmBkmsnumber, sgtGntrvaluedatefrom: $sgtGntrvaluedatefrom, sgtGntrvaluedateto: $sgtGntrvaluedateto, type: $type}'; + } +} diff --git a/lib/app/models/GlsResponseModel.dart b/lib/app/models/GlsResponseModel.dart new file mode 100644 index 0000000..9a260c2 --- /dev/null +++ b/lib/app/models/GlsResponseModel.dart @@ -0,0 +1,40 @@ +class GlsResponseModel { + String porOrgacode; + String pcaGlaccode; + String pcaGlacdesc; + String pcaGlacshort; + + GlsResponseModel({ + this.porOrgacode = "", + this.pcaGlaccode = "", + this.pcaGlacdesc = "", + this.pcaGlacshort = "", + }); + + factory GlsResponseModel.fromMap(Map map) { + return GlsResponseModel( + porOrgacode: map['porOrgacode'] ?? '', + pcaGlaccode: map['pcaGlaccode'] ?? '', + pcaGlacdesc: map['pcaGlacdesc'] ?? '', + pcaGlacshort: map['pcaGlacshort'] ?? '', + ); + } + + static List fromList(List list) { + return list.map((item) => GlsResponseModel.fromMap(item as Map)).toList(); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pcaGlaccode': pcaGlaccode, + 'pcaGlacdesc': pcaGlacdesc, + 'pcaGlacshort': pcaGlacshort, + }; + } + + @override + String toString() { + return 'GlsResponseModel{porOrgacode: $porOrgacode, pcaGlaccode: $pcaGlaccode, pcaGlacdesc: $pcaGlacdesc, pcaGlacshort: $pcaGlacshort}'; + } +} diff --git a/lib/app/models/LoginResponseModel.dart b/lib/app/models/LoginResponseModel.dart new file mode 100644 index 0000000..294936c --- /dev/null +++ b/lib/app/models/LoginResponseModel.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; + +LoginResponseModel loginResponseModelFromJson(String str) => LoginResponseModel.fromJson(json.decode(str)); + +String loginResponseModelToJson(LoginResponseModel data) => json.encode(data.toJson()); + +class LoginResponseModel { + final String name; + final String cmpCuststatus; + final dynamic cmpCustlastlogin; + final String cmpCustcode; + final String userRole; + final String jwtToken; + final String refreshToken; + final String cmpCustImage; + final bool isKycVerified; + final bool isTranPinSet; + + LoginResponseModel({ + required this.name, + required this.cmpCuststatus, + required this.cmpCustlastlogin, + required this.cmpCustcode, + required this.userRole, + required this.jwtToken, + required this.refreshToken, + required this.cmpCustImage, + required this.isKycVerified, + required this.isTranPinSet, + }); + + LoginResponseModel copyWith({ + String? name, + String? cmpCuststatus, + dynamic cmpCustlastlogin, + String? cmpCustcode, + String? userRole, + String? jwtToken, + String? refreshToken, + String? cmpCustImage, + bool? isKycVerified, + bool? isTranPinSet, + }) => + LoginResponseModel( + name: name ?? this.name, + cmpCuststatus: cmpCuststatus ?? this.cmpCuststatus, + cmpCustlastlogin: cmpCustlastlogin ?? this.cmpCustlastlogin, + cmpCustcode: cmpCustcode ?? this.cmpCustcode, + userRole: userRole ?? this.userRole, + jwtToken: jwtToken ?? this.jwtToken, + refreshToken: refreshToken ?? this.refreshToken, + cmpCustImage: cmpCustImage ?? this.cmpCustImage, + isKycVerified: isKycVerified ?? this.isKycVerified, + isTranPinSet: isTranPinSet ?? this.isTranPinSet, + ); + + factory LoginResponseModel.fromJson(Map json) => LoginResponseModel( + name: json["name"], + cmpCuststatus: json["cmpCuststatus"], + cmpCustlastlogin: json["cmpCustlastlogin"], + cmpCustcode: json["cmpCustcode"], + userRole: json["userRole"], + jwtToken: json["jwtToken"], + refreshToken: json["refreshToken"], + cmpCustImage: json["cmpCustImage"], + isKycVerified: json["isKycVerified"], + isTranPinSet: json["isTranPinSet"], + ); + + Map toJson() => { + "name": name, + "cmpCuststatus": cmpCuststatus, + "cmpCustlastlogin": cmpCustlastlogin, + "cmpCustcode": cmpCustcode, + "userRole": userRole, + "jwtToken": jwtToken, + "refreshToken": refreshToken, + "cmpCustImage": cmpCustImage, + "isKycVerified": isKycVerified, + "isTranPinSet": isTranPinSet, + }; + + @override + String toString() { + return 'LoginResponseModel{name: $name, cmpCuststatus: $cmpCuststatus, cmpCustlastlogin: $cmpCustlastlogin, cmpCustcode: $cmpCustcode, userRole: $userRole, jwtToken: $jwtToken, refreshToken: $refreshToken, cmpCustImage: $cmpCustImage, isKycVerified: $isKycVerified, isTranPinSet: $isTranPinSet}'; + } +} diff --git a/lib/app/models/RefreshToken.dart b/lib/app/models/RefreshToken.dart new file mode 100644 index 0000000..988b286 --- /dev/null +++ b/lib/app/models/RefreshToken.dart @@ -0,0 +1,28 @@ +class RefreshToken { + String refreshToken = ""; + String accessToken = ""; + + RefreshToken({ + this.refreshToken = "", + this.accessToken = "", + }); + + Map toMap() { + return { + 'refreshToken': refreshToken, + 'accessToken': accessToken, + }; + } + + factory RefreshToken.fromMap(Map map) { + return RefreshToken( + refreshToken: map['refreshToken'], + accessToken: map['accessToken'], + ); + } + + @override + String toString() { + return 'RefreshToken{refreshToken: $refreshToken, accessToken: $accessToken}'; + } +} diff --git a/lib/app/models/RegisterRequest.dart b/lib/app/models/RegisterRequest.dart new file mode 100644 index 0000000..499a28c --- /dev/null +++ b/lib/app/models/RegisterRequest.dart @@ -0,0 +1,69 @@ +class RegisterRequest { + String email = ""; + String password = ""; + String username = ""; + String phone = ""; + String name = ""; + String userRole = ""; + String channelCode = ""; + String porOrgacode = ""; + bool isOtpRequired = false; + + RegisterRequest.empty() + : this.email = "", + this.password = "", + this.username = "", + this.phone = "", + this.name = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.isOtpRequired = false; + + RegisterRequest({ + this.email = "", + this.password = "", + this.username = "", + this.phone = "", + this.name = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.isOtpRequired = false, + }); + + Map toMap() { + return { + 'email': email, + 'password': password, + 'username': username, + 'phone': phone, + 'name': name, + 'userRole': userRole, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + 'isOtpRequired': isOtpRequired, + }; + } + + factory RegisterRequest.fromMap(Map map) { + return RegisterRequest( + email: map['email'], + password: map['password'], + username: map['username'], + phone: map['phone'], + name: map['name'], + userRole: map['userRole'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + isOtpRequired: map['isOtpRequired'], + ); + } + + @override + String toString() { + return 'RegisterRequest{email: $email, password: $password, username: $username, phone: $phone, name: $name, userRole: $userRole, channelCode: $channelCode, porOrgacode: $porOrgacode, isOtpRequired: $isOtpRequired}'; + } + + +} diff --git a/lib/app/models/SendTransactionStep1ResponseModel.dart b/lib/app/models/SendTransactionStep1ResponseModel.dart new file mode 100644 index 0000000..2f50aa5 --- /dev/null +++ b/lib/app/models/SendTransactionStep1ResponseModel.dart @@ -0,0 +1,24 @@ +class SendTransactionStep1ResponseModel { + int notificationId = 0; + + SendTransactionStep1ResponseModel({ + this.notificationId = 0, + }); + + factory SendTransactionStep1ResponseModel.fromMap(Map json) { + return SendTransactionStep1ResponseModel( + notificationId: json['notificationId'] ?? 0, + ); + } + + Map toMap() { + return { + 'notificationId': notificationId, + }; + } + + @override + String toString() { + return 'SendTransactionStep1ResponseModel{notificationId: $notificationId}'; + } +} diff --git a/lib/app/models/SignupOtpRequest.dart b/lib/app/models/SignupOtpRequest.dart new file mode 100644 index 0000000..24e35ea --- /dev/null +++ b/lib/app/models/SignupOtpRequest.dart @@ -0,0 +1,62 @@ +class SignupOtpRequest { + String username = ""; + String obpPincode = ""; + String obpPintype = ""; + String email = ""; + String cmpCustcode = ""; + String pctCstycode = ""; + String channelCode = ""; + String porOrgacode = ""; + + SignupOtpRequest({ + this.username = "", + this.obpPincode = "", + this.obpPintype = "", + this.email = "", + this.cmpCustcode = "", + this.pctCstycode = "", + this.channelCode = "", + this.porOrgacode = "", + }); + + SignupOtpRequest.empty() + : this.obpPincode = "", + this.username = "", + this.obpPintype = "", + this.email = "", + this.cmpCustcode = "", + this.pctCstycode = "", + this.channelCode = "", + this.porOrgacode = ""; + + Map toMap() { + return { + 'username': username, + 'obpPincode': this.obpPincode, + 'obpPintype': this.obpPintype, + 'email': this.email, + 'cmpCustcode': this.cmpCustcode, + 'pctCstycode': this.pctCstycode, + 'channelCode': this.channelCode, + 'porOrgacode': this.porOrgacode, + }; + } + + factory SignupOtpRequest.fromMap(Map map) { + return SignupOtpRequest( + username: map['username'], + obpPincode: map['obpPincode'] ?? "", + obpPintype: map['obpPintype'] ?? "", + email: map['email'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + ); + } + + @override + String toString() { + return 'SignupOtpRequest{obpPincode: $obpPincode, username: $username, obpPintype: $obpPintype, email: $email, cmpCustcode: $cmpCustcode, pctCstycode: $pctCstycode, channelCode: $channelCode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/SignupStep3RequestModel.dart b/lib/app/models/SignupStep3RequestModel.dart new file mode 100644 index 0000000..a801b1a --- /dev/null +++ b/lib/app/models/SignupStep3RequestModel.dart @@ -0,0 +1,97 @@ +class SignupStep3RequestModel { + String username = ""; + String email = ""; + String phone = ""; + String name = ""; + String address = ""; + String identificationType = ""; + String identificationNumber = ""; + bool isKycAdded = false; + String kycType = ""; + String kycDocumentId1 = ""; + String kycDocumentId2 = ""; + String userRole = ""; + String channelCode = ""; + String porOrgacode = ""; + String dmpProdcode = ""; + + SignupStep3RequestModel.empty() + : this.username = "", + this.email = "", + this.phone = "", + this.name = "", + this.address = "", + this.identificationType = "", + this.identificationNumber = "", + this.isKycAdded = false, + this.kycType = "", + this.kycDocumentId1 = "", + this.kycDocumentId2 = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.dmpProdcode = ""; + + SignupStep3RequestModel({ + this.username = "", + this.email = "", + this.phone = "", + this.name = "", + this.address = "", + this.identificationType = "", + this.identificationNumber = "", + this.isKycAdded = false, + this.kycType = "", + this.kycDocumentId1 = "", // base64 encoded + this.kycDocumentId2 = "", // base64 encoded + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.dmpProdcode = "", + }); + + Map toMap() { + return { + 'username': username, + 'email': email, + 'phone': phone, + 'name': name, + 'address': address, + 'identificationType': identificationType, + 'identificationNumber': identificationNumber, + 'isKycAdded': isKycAdded, + 'kycType': kycType, + 'kycDocumentId1': kycDocumentId1, + 'kycDocumentId2': kycDocumentId2, + 'userRole': userRole, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + "dmpProdcode": dmpProdcode + }; + } + + factory SignupStep3RequestModel.fromMap(Map map) { + return SignupStep3RequestModel( + username: map['username'] ?? "", + email: map['email'] ?? "", + phone: map['phone'] ?? "", + name: map['name'] ?? "", + address: map['address'] ?? "", + identificationType: map['identificationType'] ?? "", + identificationNumber: map['identificationNumber'] ?? "", + isKycAdded: map['isKycAdded'] ?? false, + kycType: map['kycType'] ?? "", + kycDocumentId1: map['kycDocumentId1'] ?? "", + kycDocumentId2: map['kycDocumentId2'] ?? "", + userRole: map['userRole'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + dmpProdcode: map["dmpProdcode"] ?? "", + ); + } + + @override + String toString() { + return 'SignupStep3RequestModel{username: $username, email: $email, phone: $phone, name: $name, address: $address, identificationType: $identificationType, identificationNumber: $identificationNumber, isKycAdded: $isKycAdded, kycType: $kycType, kycDocumentId1: $kycDocumentId1, kycDocumentId2: $kycDocumentId2, userRole: $userRole, channelCode: $channelCode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/SubmitTransactionRequestModel.dart b/lib/app/models/SubmitTransactionRequestModel.dart new file mode 100644 index 0000000..8092533 --- /dev/null +++ b/lib/app/models/SubmitTransactionRequestModel.dart @@ -0,0 +1,50 @@ +class SubmitTransactionRequestModel { + final String porOrgacode; + final String pctCstycode; + final String channelCode; + final String cmpCustcode; + final String obpPincode; + final String otdTrancomment; + final String otdTranrequestid; + + SubmitTransactionRequestModel({ + required this.porOrgacode, + required this.pctCstycode, + required this.channelCode, + required this.cmpCustcode, + required this.obpPincode, + required this.otdTrancomment, + required this.otdTranrequestid, + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'obpPincode': obpPincode, + 'otdTrancomment': otdTrancomment, + 'otdTranrequestid': otdTranrequestid, + }; + } + + factory SubmitTransactionRequestModel.fromMap(Map map) { + return SubmitTransactionRequestModel( + porOrgacode: map['porOrgacode'], + pctCstycode: map['pctCstycode'], + channelCode: map['channelCode'], + cmpCustcode: map['cmpCustcode'], + obpPincode: map['obpPincode'], + otdTrancomment: map['otdTrancomment'], + otdTranrequestid: map['otdTranrequestid'], + ); + } + + @override + String toString() { + return 'TransactionRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, ' + 'channelCode: $channelCode, cmpCustcode: $cmpCustcode, obpPincode: $obpPincode, ' + 'otdTrancomment: $otdTrancomment, otdTranrequestid: $otdTranrequestid}'; + } +} diff --git a/lib/app/models/SubmitTransactionResponseModel.dart b/lib/app/models/SubmitTransactionResponseModel.dart new file mode 100644 index 0000000..e8ee18a --- /dev/null +++ b/lib/app/models/SubmitTransactionResponseModel.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; + +SubmitTransactionResponseModel submitTransactionResponseModelFromJson(String str) => SubmitTransactionResponseModel.fromJson(json.decode(str)); + +String submitTransactionResponseModelToJson(SubmitTransactionResponseModel data) => json.encode(data.toJson()); + +class SubmitTransactionResponseModel { + final String tranId; + + SubmitTransactionResponseModel({ + required this.tranId, + }); + + SubmitTransactionResponseModel copyWith({ + String? tranId, + }) => + SubmitTransactionResponseModel( + tranId: tranId ?? this.tranId, + ); + + factory SubmitTransactionResponseModel.fromJson(Map json) => SubmitTransactionResponseModel( + tranId: json["tranID"], + ); + + Map toJson() => { + "tranID": tranId, + }; +} diff --git a/lib/app/models/TransactionHistoryRequest.dart b/lib/app/models/TransactionHistoryRequest.dart new file mode 100644 index 0000000..ce18e29 --- /dev/null +++ b/lib/app/models/TransactionHistoryRequest.dart @@ -0,0 +1,40 @@ +class TransactionHistoryRequest { + String porOrgacode = ""; + String mbmBkmsnumber = ""; + String sgtGntrvaluedatefrom = ""; + String sgtGntrvaluedateto = ""; + String type = ""; + + TransactionHistoryRequest({ + this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.sgtGntrvaluedatefrom = "", + this.sgtGntrvaluedateto = "", + this.type = "", + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'sgtGntrvaluedatefrom': sgtGntrvaluedatefrom, + 'sgtGntrvaluedateto': sgtGntrvaluedateto, + 'type': type, + }; + } + + factory TransactionHistoryRequest.fromMap(Map map) { + return TransactionHistoryRequest( + porOrgacode: map['porOrgacode'] ?? '', + mbmBkmsnumber: map['mbmBkmsnumber'] ?? '', + sgtGntrvaluedatefrom: map['sgtGntrvaluedatefrom'] ?? '', + sgtGntrvaluedateto: map['sgtGntrvaluedateto'] ?? '', + type: map['type'] ?? 'pdf', + ); + } + + @override + String toString() { + return 'TransactionHistoryRequest{porOrgacode: $porOrgacode, mbmBkmsnumber: $mbmBkmsnumber, sgtGntrvaluedatefrom: $sgtGntrvaluedatefrom, sgtGntrvaluedateto: $sgtGntrvaluedateto, type: $type}'; + } +} diff --git a/lib/app/models/TransactionPinRequestModel.dart b/lib/app/models/TransactionPinRequestModel.dart new file mode 100644 index 0000000..921f013 --- /dev/null +++ b/lib/app/models/TransactionPinRequestModel.dart @@ -0,0 +1,61 @@ +class TransactionPinRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String email = ""; + String pinType = ""; + String transPincode = ""; + bool isOtpRequired = false; + + TransactionPinRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.email = "", + this.pinType = "", + this.transPincode = "", + this.isOtpRequired = false, + }); + TransactionPinRequestModel.empty():this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.email = "", + this.pinType = "", + this.transPincode = "", + this.isOtpRequired = false; + + factory TransactionPinRequestModel.fromMap(Map map) { + return TransactionPinRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + email: map['email'] ?? "", + pinType: map['pinType'] ?? "", + transPincode: map['transPincode'] ?? "", + isOtpRequired: map['isOtpRequired'] ?? false, + ); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'email': email, + 'pinType': pinType, + 'transPincode': transPincode, + 'isOtpRequired': isOtpRequired, + }; + } + + @override + String toString() { + return 'TransactionPinRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, email: $email, pinType: $pinType, transPincode: $transPincode, isOtpRequired: $isOtpRequired}'; + } +} + diff --git a/lib/app/models/TransactionPinResponseModel.dart b/lib/app/models/TransactionPinResponseModel.dart new file mode 100644 index 0000000..89c8669 --- /dev/null +++ b/lib/app/models/TransactionPinResponseModel.dart @@ -0,0 +1,28 @@ +class TransactionPinResponseModel { + double otdTranrequestid = 0.0; + String pinCode = ""; + + TransactionPinResponseModel({ + this.otdTranrequestid = 0, + this.pinCode = "", + }); + + Map toMap() { + return { + 'otdTranrequestid': otdTranrequestid, + 'pinCode': pinCode, + }; + } + + factory TransactionPinResponseModel.fromMap(Map map) { + return TransactionPinResponseModel( + otdTranrequestid: map['otdTranrequestid'] ?? 0, + pinCode: map['pinCode'] ?? '', + ); + } + + @override + String toString() { + return 'TransactionPinResponseModel{otdTranrequestid: $otdTranrequestid, pinCode: $pinCode}'; + } +} diff --git a/lib/app/models/TransactionRequestModel.dart b/lib/app/models/TransactionRequestModel.dart new file mode 100644 index 0000000..35d09f9 --- /dev/null +++ b/lib/app/models/TransactionRequestModel.dart @@ -0,0 +1,56 @@ +class TransactionRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String obpPincode = ""; + String otdTrancomment = ""; + String otdTranrequestid = ""; + + TransactionRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.obpPincode = "", + this.otdTrancomment = "", + this.otdTranrequestid = "", + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'obpPincode': obpPincode, + 'otdTrancomment': otdTrancomment, + 'otdTranrequestid': otdTranrequestid, + }; + } + + factory TransactionRequestModel.fromMap(Map map) { + return TransactionRequestModel( + porOrgacode: map['porOrgacode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + channelCode: map['channelCode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + obpPincode: map['obpPincode'] ?? '', + otdTrancomment: map['otdTrancomment'] ?? '', + otdTranrequestid: map['otdTranrequestid'] ?? '', + ); + } + + @override + String toString() { + return 'TransactionRequestModel{' + 'porOrgacode: $porOrgacode, ' + 'pctCstycode: $pctCstycode, ' + 'channelCode: $channelCode, ' + 'cmpCustcode: $cmpCustcode, ' + 'obpPincode: $obpPincode, ' + 'otdTrancomment: $otdTrancomment, ' + 'otdTranrequestid: $otdTranrequestid' + '}'; + } +} diff --git a/lib/app/models/TransactionResponseModel.dart b/lib/app/models/TransactionResponseModel.dart new file mode 100644 index 0000000..131ed32 --- /dev/null +++ b/lib/app/models/TransactionResponseModel.dart @@ -0,0 +1,22 @@ +class TransactionResponseModel { + String tranID = ""; + + TransactionResponseModel({this.tranID = ""}); + + Map toMap() { + return { + 'tranID': tranID, + }; + } + + factory TransactionResponseModel.fromMap(Map map) { + return TransactionResponseModel( + tranID: map['tranID'], + ); + } + + @override + String toString() { + return 'TransactionResponseModel{tranID: $tranID}'; + } +} diff --git a/lib/app/models/TransactionSubmitRequestModel.dart b/lib/app/models/TransactionSubmitRequestModel.dart new file mode 100644 index 0000000..9a5e203 --- /dev/null +++ b/lib/app/models/TransactionSubmitRequestModel.dart @@ -0,0 +1,147 @@ +class TransactionSubmitRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String drMbmBkmsnumber = ""; + String cmpRefcode = ""; + String drMbmBkmstitle = ""; + String drPcrCurrcode = ""; + String drPcrCurrdesc = ""; + String drPcrCurrshort = ""; + String crMbmBkmsnumber = ""; + String crMbmBkmstitle = ""; + String crPcrCurrcode = ""; + String crPcrCurrdesc = ""; + String crPcrCurrshort = ""; + String sgtGntrnarration = ""; + String dmpProdCode = ""; + String transType = ""; + String notificationId = ""; + String transMode = ""; + double sgtGntramtfc = 0; + String otdTrancomment = ""; + String pinType = ""; + String obpPincode = ""; + bool isOtpRequired = false; + + TransactionSubmitRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.cmpRefcode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drMbmBkmsnumber = "", + this.drMbmBkmstitle = "", + this.drPcrCurrcode = "", + this.drPcrCurrdesc = "", + this.drPcrCurrshort = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0, + this.otdTrancomment = "", + this.pinType = "", + this.obpPincode = "", + this.isOtpRequired = false, + }); + + TransactionSubmitRequestModel.empty() + : this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpRefcode = "", + this.cmpCustcode = "", + this.drMbmBkmsnumber = "", + this.drMbmBkmstitle = "", + this.drPcrCurrcode = "", + this.drPcrCurrdesc = "", + this.drPcrCurrshort = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0, + this.otdTrancomment = "", + this.pinType = "", + this.obpPincode = "", + this.isOtpRequired = false; + + factory TransactionSubmitRequestModel.fromMap(Map json) { + return TransactionSubmitRequestModel( + porOrgacode: json['porOrgacode'] ?? "", + pctCstycode: json['pctCstycode'] ?? "", + channelCode: json['channelCode'] ?? "", + cmpCustcode: json['cmpCustcode'] ?? "", + cmpRefcode: json['cmpRefcode'] ?? "", + drMbmBkmsnumber: json['drMbmBkmsnumber'] ?? "", + drMbmBkmstitle: json['drMbmBkmstitle'] ?? "", + drPcrCurrcode: json['drPcrCurrcode'] ?? "", + drPcrCurrdesc: json['drPcrCurrdesc'] ?? "", + drPcrCurrshort: json['drPcrCurrshort'] ?? "", + crMbmBkmsnumber: json['crMbmBkmsnumber'] ?? "", + crMbmBkmstitle: json['crMbmBkmstitle'] ?? "", + crPcrCurrcode: json['crPcrCurrcode'] ?? "", + crPcrCurrdesc: json['crPcrCurrdesc'] ?? "", + crPcrCurrshort: json['crPcrCurrshort'] ?? "", + sgtGntrnarration: json['sgtGntrnarration'] ?? "", + dmpProdCode: json['dmpProdCode'] ?? "", + transType: json['transType'] ?? "", + notificationId: json['notificationId'] ?? "", + transMode: json['transMode'] ?? "", + sgtGntramtfc: json['sgtGntramtfc'] ?? 0.0, + otdTrancomment: json['otdTrancomment'] ?? "", + pinType: json['pinType'] ?? "", + obpPincode: json['obpPincode'] ?? "", + isOtpRequired: json['isOtpRequired'] ?? false, + ); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpRefcode': cmpRefcode, + 'cmpCustcode': cmpCustcode, + 'drMbmBkmsnumber': drMbmBkmsnumber, + 'drMbmBkmstitle': drMbmBkmstitle, + 'drPcrCurrcode': drPcrCurrcode, + 'drPcrCurrdesc': drPcrCurrdesc, + 'drPcrCurrshort': drPcrCurrshort, + 'crMbmBkmsnumber': crMbmBkmsnumber, + 'crMbmBkmstitle': crMbmBkmstitle, + 'crPcrCurrcode': crPcrCurrcode, + 'crPcrCurrdesc': crPcrCurrdesc, + 'crPcrCurrshort': crPcrCurrshort, + 'sgtGntrnarration': sgtGntrnarration, + 'dmpProdCode': dmpProdCode, + 'transType': transType, + 'notificationId': notificationId, + 'transMode': transMode, + 'sgtGntramtfc': sgtGntramtfc, + 'otdTrancomment': otdTrancomment, + 'pinType': pinType, + 'obpPincode': obpPincode, + 'isOtpRequired': isOtpRequired, + }; + } + + @override + String toString() { + return 'TransactionSubmitRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, drMbmBkmsnumber: $drMbmBkmsnumber, cmpRefcode: $cmpRefcode, drMbmBkmstitle: $drMbmBkmstitle, drPcrCurrcode: $drPcrCurrcode, drPcrCurrdesc: $drPcrCurrdesc, drPcrCurrshort: $drPcrCurrshort, crMbmBkmsnumber: $crMbmBkmsnumber, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrcode: $crPcrCurrcode, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrshort: $crPcrCurrshort, sgtGntrnarration: $sgtGntrnarration, dmpProdCode: $dmpProdCode, transType: $transType, notificationId: $notificationId, transMode: $transMode, sgtGntramtfc: $sgtGntramtfc, otdTrancomment: $otdTrancomment, pinType: $pinType, obpPincode: $obpPincode, isOtpRequired: $isOtpRequired}'; + } +} diff --git a/lib/app/models/TransactionSubmitResponseModel.dart b/lib/app/models/TransactionSubmitResponseModel.dart new file mode 100644 index 0000000..9b4cbf9 --- /dev/null +++ b/lib/app/models/TransactionSubmitResponseModel.dart @@ -0,0 +1,26 @@ +class TransactionSubmitResponseModel { + double mbmBkmsbalance = 0.0; + + TransactionSubmitResponseModel({ + this.mbmBkmsbalance = 0.0, + }); + + TransactionSubmitResponseModel.empty() : this.mbmBkmsbalance = 0.0; + + factory TransactionSubmitResponseModel.fromMap(Map json) { + return TransactionSubmitResponseModel( + mbmBkmsbalance: json['mbmBkmsbalance'] ?? 0.0, + ); + } + + Map toMap() { + return { + 'mbmBkmsbalance': mbmBkmsbalance, + }; + } + + @override + String toString() { + return 'TransactionSubmitResponseModel{mbmBkmsbalance: $mbmBkmsbalance}'; + } +} diff --git a/lib/app/models/UserActivity.dart b/lib/app/models/UserActivity.dart new file mode 100644 index 0000000..7220a39 --- /dev/null +++ b/lib/app/models/UserActivity.dart @@ -0,0 +1,48 @@ +class UserActivity { + int id; + String porOrgacode; + String cmpCustcode; + DateTime date; + String channel; + String deviceName; + String activity; + + UserActivity({ + required this.id, + required this.porOrgacode, + required this.cmpCustcode, + required this.date, + required this.channel, + required this.deviceName, + required this.activity, + }); + + Map toMap() { + return { + 'id': id, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'date': date.toIso8601String(), + 'channel': channel, + 'deviceName': deviceName, + 'activity': activity, + }; + } + + factory UserActivity.fromMap(Map map) { + return UserActivity( + id: map['id'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + date: DateTime.parse(map['date'] ?? ''), + channel: map['channel'] ?? '01', + deviceName: map['deviceName'] ?? '', + activity: map['activity'] ?? '', + ); + } + + @override + String toString() { + return 'LoginActivity{id: $id, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, date: $date, channel: $channel, deviceName: $deviceName, activity: $activity}'; + } +} diff --git a/lib/app/models/UserActivityResponseModel.dart b/lib/app/models/UserActivityResponseModel.dart new file mode 100644 index 0000000..03e2ece --- /dev/null +++ b/lib/app/models/UserActivityResponseModel.dart @@ -0,0 +1,19 @@ +import 'UserActivity.dart'; + +class UserActivityResponseModel { + List userActivity = []; + + UserActivityResponseModel({required this.userActivity}); + + factory UserActivityResponseModel.fromMap(dynamic list) { + return UserActivityResponseModel( + userActivity: List.from( + list.map((map) => UserActivity.fromMap(map)), + ), + ); + } + + List> toMap() { + return userActivity.map((transaction) => transaction.toMap()).toList(); + } +} \ No newline at end of file diff --git a/lib/app/models/UserInfo.dart b/lib/app/models/UserInfo.dart new file mode 100644 index 0000000..73382b4 --- /dev/null +++ b/lib/app/models/UserInfo.dart @@ -0,0 +1,51 @@ +import 'package:flutter/cupertino.dart'; +import 'package:get/get.dart'; +import 'package:json_annotation/json_annotation.dart'; + +// @JsonSerializable(includeIfNull: false) + + +class UserInfo { + String name; + String userRole; + String porOrgacode; + String pctCstycode; + String plcLocalcode; + String channelCode; + String cmpCustpassword; + String newCustpassword; + String cmpCustcode; + String cmpUserId; + String cmpCuststatus; + String jwtToken; + String refreshToken; + bool isKycVerified; + bool isTranPinSet; + String cmpCustlastlogin; + + + UserInfo({ + this.name = '', + this.refreshToken = '', + this.userRole = '', + this.cmpCustcode = '', + this.isKycVerified = false, + this.isTranPinSet = false, + this.cmpUserId = '', + this.porOrgacode = '', + this.channelCode = '', + /* this.cmpAccountno = ''*/ this.cmpCustlastlogin = '', + this.cmpCustpassword = '', + this.cmpCuststatus = '', + /* this.cmpFirstname = '', this.cmpIdennumber = '', this.cmpLastname = '', this.cmpUserIdType = ''*/ this.jwtToken = '', + this.newCustpassword = '', + /*this.obpPincode = '',*/ this.pctCstycode = '', + /* this.phoneNo = '',*/ this.plcLocalcode = '', + /*this.token = ''*/ + }); + + @override + String toString() { + return 'UserInfo{name: $name, userRole: $userRole, porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, plcLocalcode: $plcLocalcode, channelCode: $channelCode, cmpCustpassword: $cmpCustpassword, newCustpassword: $newCustpassword, cmpCustcode: $cmpCustcode, cmpUserId: $cmpUserId, cmpCuststatus: $cmpCuststatus, jwtToken: $jwtToken, refreshToken: $refreshToken, isKycVerified: $isKycVerified, isTranPinSet: $isTranPinSet, cmpCustlastlogin: $cmpCustlastlogin}'; + } +} diff --git a/lib/app/models/VerifyLoginOtpRequest.dart b/lib/app/models/VerifyLoginOtpRequest.dart new file mode 100644 index 0000000..6749c75 --- /dev/null +++ b/lib/app/models/VerifyLoginOtpRequest.dart @@ -0,0 +1,40 @@ +class VerifyLoginOtpRequest { + String email = ""; + String password = ""; + String channelCode = ""; + String porOrgacode = ""; + String obpPincode = ""; + + VerifyLoginOtpRequest({ + this.email = "", + this.password = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = "", + }); + + Map toMap() { + return { + 'email': this.email, + 'password': this.password, + 'channelCode': this.channelCode, + 'porOrgacode': this.porOrgacode, + 'obpPincode': this.obpPincode, + }; + } + + factory VerifyLoginOtpRequest.fromMap(Map map) { + return VerifyLoginOtpRequest( + email: map['email'] ?? "", + password: map['password'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + obpPincode: map['obpPincode'] ?? "", + ); + } + + @override + String toString() { + return 'VerifyLoginOtpRequest{email: $email, password: $password, channelCode: $channelCode, porOrgacode: $porOrgacode, obpPincode: $obpPincode}'; + } +} diff --git a/lib/app/models/VerifySignupOtpRequest.dart b/lib/app/models/VerifySignupOtpRequest.dart new file mode 100644 index 0000000..b52fe3a --- /dev/null +++ b/lib/app/models/VerifySignupOtpRequest.dart @@ -0,0 +1,52 @@ +class VerifySignupOtpRequest { + String username = ""; + String email = ""; + String phone = ""; + String channelCode = ""; + String porOrgacode = ""; + String obpPincode = ""; + + VerifySignupOtpRequest({ + this.username = "", + this.email = "", + this.phone = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = "", + }); + + VerifySignupOtpRequest.empty() + : this.username = "", + this.email = "", + this.phone = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = ""; + + Map toMap() { + return { + 'username': username, + 'email': email, + 'phone': phone, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + 'obpPincode': obpPincode, + }; + } + + factory VerifySignupOtpRequest.fromMap(Map map) { + return VerifySignupOtpRequest( + username: map['username'], + email: map['email'], + phone: map['phone'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + obpPincode: map['obpPincode'], + ); + } + + @override + String toString() { + return 'VerifySignupOtpRequest{username: $username, email: $email, phone: $phone, channelCode: $channelCode, porOrgacode: $porOrgacode, obpPincode: $obpPincode}'; + } +} diff --git a/lib/app/models/ViewBalanceRequestModel.dart b/lib/app/models/ViewBalanceRequestModel.dart new file mode 100644 index 0000000..c8e2cd1 --- /dev/null +++ b/lib/app/models/ViewBalanceRequestModel.dart @@ -0,0 +1,25 @@ +class ViewBalanceRequestModel { + String cmpCustcode = ""; + String mbmBkmsNumber = ""; + + ViewBalanceRequestModel({this.cmpCustcode = "", this.mbmBkmsNumber = ""}); + + Map toMap() { + return { + 'cmpCustcode': cmpCustcode, + 'mbmBkmsNumber': mbmBkmsNumber, + }; + } + + factory ViewBalanceRequestModel.fromMap(Map map) { + return ViewBalanceRequestModel( + cmpCustcode: map['cmpCustcode'], + mbmBkmsNumber: map['mbmBkmsNumber'], + ); + } + + @override + String toString() { + return 'ViewBalanceRequestModel{cmpCustcode: $cmpCustcode, mbmBkmsNumber: $mbmBkmsNumber}'; + } +} diff --git a/lib/app/models/ViewBalanceResponseModel.dart b/lib/app/models/ViewBalanceResponseModel.dart new file mode 100644 index 0000000..150afc2 --- /dev/null +++ b/lib/app/models/ViewBalanceResponseModel.dart @@ -0,0 +1,22 @@ +class ViewBalanceResponseModel { + String mbmBkmsbalance = ""; + + ViewBalanceResponseModel({this.mbmBkmsbalance = ""}); + + Map toMap() { + return { + 'mbmBkmsbalance': mbmBkmsbalance, + }; + } + + factory ViewBalanceResponseModel.fromMap(Map map) { + return ViewBalanceResponseModel( + mbmBkmsbalance: map['mbmBkmsbalance'], + ); + } + + @override + String toString() { + return 'ViewBalanceResponseModel{mbmBkmsbalance: $mbmBkmsbalance}'; + } +} diff --git a/lib/app/models/accept_receive_transaction.dart b/lib/app/models/accept_receive_transaction.dart new file mode 100644 index 0000000..05f0e36 --- /dev/null +++ b/lib/app/models/accept_receive_transaction.dart @@ -0,0 +1,46 @@ +class AcceptReceiveTransactionModel { + int id; + String cmpTranpin; + bool isAccepted; + String cmpCustcode; + String cmpRefcode; + String porOrgacode; + + AcceptReceiveTransactionModel({ + required this.id, + required this.cmpTranpin, + required this.isAccepted, + required this.cmpCustcode, + required this.cmpRefcode, + required this.porOrgacode, + }); + + /// Convert object to a Map + Map toMap() { + return { + 'id': id, + 'cmpTranpin': cmpTranpin, + 'isAccepted': isAccepted, + 'cmpCustcode': cmpCustcode, + 'cmpRefcode': cmpRefcode, + 'porOrgacode': porOrgacode, + }; + } + + /// Create object from a Map + factory AcceptReceiveTransactionModel.fromMap(Map map) { + return AcceptReceiveTransactionModel( + id: map['id'], + cmpTranpin: map['cmpTranpin'], + isAccepted: map['isAccepted'], + cmpCustcode: map['cmpCustcode'], + cmpRefcode: map['cmpRefcode'], + porOrgacode: map['porOrgacode'], + ); + } + + @override + String toString() { + return 'AcceptReceiveTransactionModel{id: $id, cmpTranpin: $cmpTranpin, isAccepted: $isAccepted, cmpCustcode: $cmpCustcode, cmpRefcode: $cmpRefcode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/accountStatementResponseModel.dart b/lib/app/models/accountStatementResponseModel.dart new file mode 100644 index 0000000..0ca898d --- /dev/null +++ b/lib/app/models/accountStatementResponseModel.dart @@ -0,0 +1,125 @@ +class AccountStatementResponseModel { + int id = 0; + String porOrgacode = ""; + String drMbmBkmsnumber = ""; + String sgtReceiveNodeId = ""; + String sgtSentNodeId = ""; + bool batAcnttranReversed = false; + String crMbmBkmsnumber = ""; + String dmpProdcode = ""; + double crMbmBkmsbalance = 0.0; + double drMbmBkmsbalance = 0.0; + String drmbmBkmstitle = ""; + String cmpCustcode = ""; + String crMbmBkmstitle = ""; + String sgtSentGntrnumber = ""; + String drSgtGntrdate = ""; + String? crSgtGntrdate = ""; + double sgtGntramt = 0.0; + bool batAcnttranSend = false; + bool batAcnttranReceived = false; + String? sgtReceiveGntrnumber = ""; + String drpcrCurrdesc = ""; + String drPcrCurrcode = ""; + String drPcrCurrshort = ""; + String crPcrCurrdesc = ""; + String crPcrCurrcode = ""; + String crPcrCurrshort = ""; + + AccountStatementResponseModel({this.id = 0, this.porOrgacode = "", this.sgtReceiveNodeId = "" ,this.batAcnttranReversed = false, this.sgtSentNodeId ="",this.drMbmBkmsnumber = "", this.crMbmBkmsnumber = "", this.dmpProdcode = "", this.crMbmBkmsbalance = 0.0, this.drMbmBkmsbalance = 0.0, this.drmbmBkmstitle = "", this.cmpCustcode = "", this.crMbmBkmstitle = "", this.sgtSentGntrnumber = "", this.drSgtGntrdate = "", this.crSgtGntrdate = "", this.sgtGntramt = 0.0, this.batAcnttranSend = false, this.batAcnttranReceived = false, this.sgtReceiveGntrnumber = "", this.drpcrCurrdesc = "", this.drPcrCurrcode = "", this.drPcrCurrshort = "", this.crPcrCurrdesc = "", this.crPcrCurrcode = "", this.crPcrCurrshort = ""}); + + AccountStatementResponseModel.empty() + : this.id = 0, + this.porOrgacode = "", + this.drMbmBkmsnumber = "", + this.crMbmBkmsnumber = "", + this.sgtReceiveNodeId = "", + this.sgtSentNodeId = "", + this.batAcnttranReversed = false, + this.dmpProdcode = "", + this.crMbmBkmsbalance = 0.0, + this.drMbmBkmsbalance = 0.0, + this.drmbmBkmstitle = "", + this.batAcnttranSend = false, + this.cmpCustcode = "", + this.crMbmBkmstitle = "", + this.sgtSentGntrnumber = "", + this.drSgtGntrdate = "", + this.crSgtGntrdate = "", + this.sgtGntramt = 0.0, + this.batAcnttranReceived = false, + this.sgtReceiveGntrnumber = "", + this.drpcrCurrdesc = "", + this.drPcrCurrcode = "", + this.drPcrCurrshort = "", + this.crPcrCurrdesc = "", + this.crPcrCurrcode = "", + this.crPcrCurrshort = ""; + + Map toMap() { + return { + 'id': this.id, + 'porOrgacode': this.porOrgacode, + 'drMbmBkmsnumber': this.drMbmBkmsnumber, + 'sgtReceiveNodeId': this.sgtReceiveNodeId, + 'sgtSentNodeId': this.sgtSentNodeId, + 'batAcnttranReversed': this.batAcnttranReversed, + 'crMbmBkmsnumber': this.crMbmBkmsnumber, + 'dmpProdcode': this.dmpProdcode, + 'crMbmBkmsbalance': this.crMbmBkmsbalance, + 'drMbmBkmsbalance': this.drMbmBkmsbalance, + 'drmbmBkmstitle': this.drmbmBkmstitle, + 'cmpCustcode': this.cmpCustcode, + 'crMbmBkmstitle': this.crMbmBkmstitle, + 'sgtSentGntrnumber': this.sgtSentGntrnumber, + 'drSgtGntrdate': this.drSgtGntrdate, + 'crSgtGntrdate': this.crSgtGntrdate, + 'sgtGntramt': this.sgtGntramt, + 'batAcnttranSend': this.batAcnttranSend, + 'batAcnttranReceived': this.batAcnttranReceived, + 'sgtReceiveGntrnumber': this.sgtReceiveGntrnumber, + 'drpcrCurrdesc': this.drpcrCurrdesc, + 'drPcrCurrcode': this.drPcrCurrcode, + 'drPcrCurrshort': this.drPcrCurrshort, + 'crPcrCurrdesc': this.crPcrCurrdesc, + 'crPcrCurrcode': this.crPcrCurrcode, + 'crPcrCurrshort': this.crPcrCurrshort, + }; + } + + factory AccountStatementResponseModel.fromMap(Map map) { + return AccountStatementResponseModel( + id: map['id'] as int, + porOrgacode: map['porOrgacode'] ?? "", + drMbmBkmsnumber: map['drMbmBkmsnumber'] ?? "", + sgtReceiveNodeId : map['sgtReceiveNodeId'] ?? "", + sgtSentNodeId : map['sgtSentNodeId'] ?? "", + batAcnttranReversed : map['batAcnttranReversed'] ?? false, + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + crMbmBkmsbalance: map['crMbmBkmsbalance'] ?? 0.0, + drMbmBkmsbalance: map['drMbmBkmsbalance'] ?? 0.0, + drmbmBkmstitle: map['drmbmBkmstitle'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + sgtSentGntrnumber: map['sgtSentGntrnumber'] ?? "", + drSgtGntrdate: map['drSgtGntrdate'] ?? "", + crSgtGntrdate: map['crSgtGntrdate'] ?? "", + sgtGntramt: map['sgtGntramt'] ?? 0.0, + batAcnttranSend: map['batAcnttranSend'] ?? false, + batAcnttranReceived: map['batAcnttranReceived'] ?? false, + sgtReceiveGntrnumber: map['sgtReceiveGntrnumber'] ?? "", + drpcrCurrdesc: map['drpcrCurrdesc'] ?? "", + drPcrCurrcode: map['drPcrCurrcode'] ?? "", + drPcrCurrshort: map['drPcrCurrshort'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + ); + } + + @override + String toString() { + return 'AccountStatementResponseModel{id: $id, porOrgacode: $porOrgacode, drMbmBkmsnumber: $drMbmBkmsnumber, sgtReceiveNodeId: $sgtReceiveNodeId, sgtSentNodeId: $sgtSentNodeId, batAcnttranReversed: $batAcnttranReversed, crMbmBkmsnumber: $crMbmBkmsnumber, dmpProdcode: $dmpProdcode, crMbmBkmsbalance: $crMbmBkmsbalance, drMbmBkmsbalance: $drMbmBkmsbalance, drmbmBkmstitle: $drmbmBkmstitle, cmpCustcode: $cmpCustcode, crMbmBkmstitle: $crMbmBkmstitle, sgtSentGntrnumber: $sgtSentGntrnumber, drSgtGntrdate: $drSgtGntrdate, crSgtGntrdate: $crSgtGntrdate, sgtGntramt: $sgtGntramt, batAcnttranSend: $batAcnttranSend, batAcnttranReceived: $batAcnttranReceived, sgtReceiveGntrnumber: $sgtReceiveGntrnumber, drpcrCurrdesc: $drpcrCurrdesc, drPcrCurrcode: $drPcrCurrcode, drPcrCurrshort: $drPcrCurrshort, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrcode: $crPcrCurrcode, crPcrCurrshort: $crPcrCurrshort}'; + } +} diff --git a/lib/app/models/account_statment_model.dart b/lib/app/models/account_statment_model.dart new file mode 100644 index 0000000..3ac8ad1 --- /dev/null +++ b/lib/app/models/account_statment_model.dart @@ -0,0 +1,43 @@ +// To parse this JSON data, do +// +// final accountStatment = accountStatmentFromJson(jsonString); + +import 'dart:convert'; + +List accountStatmentFromJson(String str) => + List.from( + json.decode(str).map((x) => AccountStatementModel.fromJson(x))); + +class AccountStatementModel { + final String? tranId; + final String? sgtGntrCreatedAt; + final String? sgtGntrNarration; + final String? sgtGntrvaluedate; + final String? deposit; + final String? withdrawal; + final String? status; + final String? sgtGntramt; + + AccountStatementModel({ + this.tranId, + this.sgtGntrCreatedAt, + this.sgtGntrNarration, + this.sgtGntrvaluedate, + this.deposit, + this.withdrawal, + this.status, + this.sgtGntramt, + }); + + factory AccountStatementModel.fromJson(Map json) => + AccountStatementModel( + tranId: json["tranID"], + sgtGntrCreatedAt: json["sgtGntrCreatedAt"], + sgtGntrNarration: json["sgtGntrNarration"], + sgtGntrvaluedate: json["sgtGntrvaluedate"], + deposit: json["deposit"], + withdrawal: json["withdrawal"], + status: json["status"], + sgtGntramt: json["sgtGntramt"], + ); +} diff --git a/lib/app/models/chanange_password_params.dart b/lib/app/models/chanange_password_params.dart new file mode 100644 index 0000000..45b674e --- /dev/null +++ b/lib/app/models/chanange_password_params.dart @@ -0,0 +1,36 @@ +// To parse this JSON data, do +// +// final changePasswordParams = changePasswordParamsFromJson(jsonString); + +import 'dart:convert'; + +ChangePasswordParams changePasswordParamsFromJson(String str) => + ChangePasswordParams.fromJson(json.decode(str)); + +String changePasswordParamsToJson(ChangePasswordParams data) => + json.encode(data.toJson()); + +class ChangePasswordParams { + final String? newPassword; + final String? email; + final String? oldPassword; + + ChangePasswordParams({ + this.newPassword, + this.email, + this.oldPassword, + }); + + factory ChangePasswordParams.fromJson(Map json) => + ChangePasswordParams( + newPassword: json["newPassword"], + email: json["email"], + oldPassword: json["oldPassword"], + ); + + Map toJson() => { + "newPassword": newPassword, + "email": email, + "oldPassword": oldPassword, + }; +} diff --git a/lib/app/models/create_transition_otp_model.dart b/lib/app/models/create_transition_otp_model.dart new file mode 100644 index 0000000..0985844 --- /dev/null +++ b/lib/app/models/create_transition_otp_model.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; + +class CreateTransactionPinRequest { + String newTransPincode; + String channelCode; + String pctCstycode; + String porOrgacode; + String cmpCustcode; + bool isOtpRequired; + String pinType; + CreateTransactionPinRequest({ + required this.newTransPincode, + required this.channelCode, + required this.pctCstycode, + required this.porOrgacode, + required this.cmpCustcode, + required this.isOtpRequired, + required this.pinType, + }); + + Map toMap() { + final result = {}; + + result.addAll({'newTransPincode': newTransPincode}); + result.addAll({'channelCode': channelCode}); + result.addAll({'pctCstycode': pctCstycode}); + result.addAll({'porOrgacode': porOrgacode}); + result.addAll({'cmpCustcode': cmpCustcode}); + result.addAll({'isOtpRequired': isOtpRequired}); + result.addAll({'pinType': pinType}); + + return result; + } + + factory CreateTransactionPinRequest.fromMap(Map map) { + return CreateTransactionPinRequest( + newTransPincode: map['newTransPincode'] ?? '', + channelCode: map['channelCode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + isOtpRequired: map['isOtpRequired'] ?? false, + pinType: map['pinType'] ?? '', + ); + } + + String toJson() => json.encode(toMap()); + + factory CreateTransactionPinRequest.fromJson(String source) => + CreateTransactionPinRequest.fromMap(json.decode(source)); +} diff --git a/lib/app/models/dashboard_response_model.dart b/lib/app/models/dashboard_response_model.dart new file mode 100644 index 0000000..b227bca --- /dev/null +++ b/lib/app/models/dashboard_response_model.dart @@ -0,0 +1,59 @@ + +import 'DepositAccountResponse.dart'; + +class DashBoardResponseModel { + List deposit = []; + + DashBoardResponseModel({required this.deposit}); + + factory DashBoardResponseModel.fromMap(dynamic map) { + return DashBoardResponseModel( + deposit: List.from( + ((map ?? []) as List).map((x) => DepositAccount.fromMap(x)) ?? [], + ), + ); + } + + Map toMap() { + return { + 'deposit': deposit.map((x) => x.toMap()).toList(), + }; + } +} + +class SampleDashboardData { + // static DashBoardResponseModel getDashboardModel(String responseFromServer) { + // String response = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000012\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000014\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":495000,\"accountBalance\":495000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000016\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":499999,\"accountBalance\":499999}]}"; + // + // String oneLoanAndOneDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000016\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":499999,\"accountBalance\":499999}]}"; + // + // String oneLoanAndZeroDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[]}"; + // + // String zeroLoanAndOneDeposit = "{\"loan\":[],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501}]}"; + // + // String zeroLoanAndMultipleDeposit = + // "{\"loan\":[],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // String multipleLoanAndZeroDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[]}"; + // + // String oneLoanAndMultipleDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // String oneDepositAndMultipleLoan = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501}]}"; + // + // String multipleDepositAndMultipleLoan = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // Map jsonMap = json.decode(zeroLoanAndMultipleDeposit); + // DashBoardResponseModel dashboardResponse = DashBoardResponseModel.fromMap(jsonMap); + // + // SessionCache.instance.depositAccountList.value = dashboardResponse.deposit; + // SessionCache.instance.loanAccountList.value = dashboardResponse.loan; + // return dashboardResponse; + // } +} diff --git a/lib/app/models/evaluated_cuency_model.dart b/lib/app/models/evaluated_cuency_model.dart new file mode 100644 index 0000000..ee37c39 --- /dev/null +++ b/lib/app/models/evaluated_cuency_model.dart @@ -0,0 +1,62 @@ +class EvaluatedCurrencyModel { + String pcrCurrcode = ""; + double sgtGntramtfc = 0.0; + double serviceCharges = 0.0; + double targetPerEratrateact = 0.0; + + EvaluatedCurrencyModel({ + this.pcrCurrcode = "", + this.sgtGntramtfc = 0.0, + this.serviceCharges = 0.0, + this.targetPerEratrateact = 0.0, + }); + + EvaluatedCurrencyModel.empty() + : this.pcrCurrcode = "", + this.sgtGntramtfc = 0.0, + this.serviceCharges = 0.0, + this.targetPerEratrateact = 0.0; + + Map toMap() { + return { + 'pcrCurrcode': this.pcrCurrcode, + 'sgtGntramtfc': this.sgtGntramtfc, + 'serviceCharges': this.serviceCharges, + 'targetPerEratrateact': this.targetPerEratrateact, + }; + } + + factory EvaluatedCurrencyModel.fromMap(Map map) { + return EvaluatedCurrencyModel( + pcrCurrcode: map['pcrCurrcode'] ?? "", + sgtGntramtfc: map['sgtGntramtfc'] ?? 0.0, + serviceCharges: map['serviceCharges'] ?? 0.0, + targetPerEratrateact: map['targetPerEratrateact'] ?? 0.0, + ); + } + + @override + String toString() { + return 'EvaluatedCurrencyModel{pcrCurrcode: $pcrCurrcode, sgtGntramtfc: $sgtGntramtfc, serviceCharges: $serviceCharges, targetPerEratrateact: $targetPerEratrateact}'; + } + +// Factory constructor to create an instance from a JSON map +// factory EvaluatedCurrencyModel.fromJson(Map json) { +// return EvaluatedCurrencyModel( +// pcrCurrcode: json['pcrCurrcode'] as String, +// sgtGntramtfc: (json['sgtGntramtfc'] as num).toDouble(), +// serviceCharges: (json['serviceCharges'] as num).toDouble(), +// targetPerEratrateact: (json['targetPerEratrateact'] as num).toDouble(), +// ); +// } +// +// // Method to convert an instance to a JSON map +// Map toJson() { +// return { +// 'pcrCurrcode': pcrCurrcode, +// 'sgtGntramtfc': sgtGntramtfc, +// 'serviceCharges': serviceCharges, +// 'targetPerEratrateact': targetPerEratrateact, +// }; +// } +} diff --git a/lib/app/models/finger_print_info.dart b/lib/app/models/finger_print_info.dart new file mode 100644 index 0000000..f0f7f0d --- /dev/null +++ b/lib/app/models/finger_print_info.dart @@ -0,0 +1,36 @@ +class FingerPrintInfo { + String porOrgacode; + String channelCode; + String cmpUserId; + String cmpCustpassword; + + FingerPrintInfo({ + this.porOrgacode = '', + this.channelCode = '', + this.cmpUserId = '', + this.cmpCustpassword = '', + }); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'channelCode': this.channelCode, + 'cmpUserId': this.cmpUserId, + 'cmpCustpassword': this.cmpCustpassword, + }; + } + + factory FingerPrintInfo.fromMap(Map map) { + return FingerPrintInfo( + porOrgacode: map['porOrgacode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpUserId: map['cmpUserId'] ?? "", + cmpCustpassword: map['cmpCustpassword'] ?? "", + ); + } + + @override + String toString() { + return '{porOrgacode: $porOrgacode, channelCode: $channelCode, cmpUserId: $cmpUserId, cmpCustpassword: $cmpCustpassword}'; + } +} diff --git a/lib/app/models/identity_drop_down_model.dart b/lib/app/models/identity_drop_down_model.dart new file mode 100644 index 0000000..520c2ce --- /dev/null +++ b/lib/app/models/identity_drop_down_model.dart @@ -0,0 +1,12 @@ +class IdentityDropDowModel { + identityType identity; + String label; + + IdentityDropDowModel({required this.identity, required this.label}); +} + +enum identityType { + identity, + ssntaxpayer, + passport, +} diff --git a/lib/app/models/login_request_model.dart b/lib/app/models/login_request_model.dart new file mode 100644 index 0000000..f775f00 --- /dev/null +++ b/lib/app/models/login_request_model.dart @@ -0,0 +1,35 @@ + + +import '../core/constants/api_keys.dart'; + +class LoginRequestModel { + final String username; + final String password; + final String channelCode; + final String porOrgacode; + + LoginRequestModel({ + required this.username, + required this.password, + required this.channelCode, + required this.porOrgacode, + }); + + factory LoginRequestModel.fromJson(Map json) { + return LoginRequestModel( + username: json[ApiKeys.cmpUserId], + password: json[ApiKeys.cmpCustpassword], + channelCode: json[ApiKeys.channelCode], + porOrgacode: json[ApiKeys.porOrgacode], + ); + } + + Map toJson() { + final Map data = {}; + data[ApiKeys.cmpUserId] = username; + data[ApiKeys.cmpCustpassword] = password; + data[ApiKeys.channelCode] = channelCode; + data[ApiKeys.porOrgacode] = porOrgacode; + return data; + } +} diff --git a/lib/app/models/product_model.dart b/lib/app/models/product_model.dart new file mode 100644 index 0000000..a9420e1 --- /dev/null +++ b/lib/app/models/product_model.dart @@ -0,0 +1,43 @@ +class ProductDepositModel { + String porOrgacode; + String dmpProdcode; + String dmpProddesc; + String dmpProdshort; + String pcrCurrcode; + bool dmpProdactive; + + ProductDepositModel({ + required this.porOrgacode, + required this.dmpProdcode, + required this.dmpProddesc, + required this.dmpProdshort, + required this.pcrCurrcode, + required this.dmpProdactive, + }); + + factory ProductDepositModel.fromJson(Map json) { + return ProductDepositModel( + porOrgacode: json['porOrgacode'], + dmpProdcode: json['dmpProdcode'], + dmpProddesc: json['dmpProddesc'], + dmpProdshort: json['dmpProdshort'], + pcrCurrcode: json['pcrCurrcode'], + dmpProdactive: json['dmpProdactive'], + ); + } + + Map toJson() { + return { + 'porOrgacode': porOrgacode, + 'dmpProdcode': dmpProdcode, + 'dmpProddesc': dmpProddesc, + 'dmpProdshort': dmpProdshort, + 'pcrCurrcode': pcrCurrcode, + 'dmpProdactive': dmpProdactive, + }; + } + + static List productListFromJson(List jsonList) { + return jsonList.map((json) => ProductDepositModel.fromJson(json)).toList(); + } +} diff --git a/lib/app/models/resen_ot_chanange_trans_pin.dart b/lib/app/models/resen_ot_chanange_trans_pin.dart new file mode 100644 index 0000000..c50d193 --- /dev/null +++ b/lib/app/models/resen_ot_chanange_trans_pin.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +class ResendOtpChangeTransPin { + String? oldTransPincode; + String? newTransPincode; + String? channelCode; + String? pctCstycode; + String? porOrgacode; + String? cmpCustcode; + bool? isOtpRequire; + String? pinType; + + ResendOtpChangeTransPin({ + this.oldTransPincode, + this.newTransPincode, + this.channelCode, + this.pctCstycode, + this.porOrgacode, + this.cmpCustcode, + this.isOtpRequire, + this.pinType, + }); + + Map toMap() { + final result = {}; + + if (oldTransPincode != null) { + result.addAll({'oldTransPincode': oldTransPincode}); + } + if (newTransPincode != null) { + result.addAll({'newTransPincode': newTransPincode}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (pctCstycode != null) { + result.addAll({'pctCstycode': pctCstycode}); + } + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (cmpCustcode != null) { + result.addAll({'cmpCustcode': cmpCustcode}); + } + if (isOtpRequire != null) { + result.addAll({'isOtpRequire': isOtpRequire}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + + return result; + } + + factory ResendOtpChangeTransPin.fromMap(Map map) { + return ResendOtpChangeTransPin( + oldTransPincode: map['oldTransPincode'], + newTransPincode: map['newTransPincode'], + channelCode: map['channelCode'], + pctCstycode: map['pctCstycode'], + porOrgacode: map['porOrgacode'], + cmpCustcode: map['cmpCustcode'], + isOtpRequire: map['isOtpRequire'], + pinType: map['pinType'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpChangeTransPin.fromJson(String source) => + ResendOtpChangeTransPin.fromMap(json.decode(source)); +} diff --git a/lib/app/models/resend_ot_login_model.dart b/lib/app/models/resend_ot_login_model.dart new file mode 100644 index 0000000..891b19c --- /dev/null +++ b/lib/app/models/resend_ot_login_model.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +class ResendOtpLoginModel { + String? username; + String? channelCode; + String? porOrgacode; + String? email; + bool? isOtpRequire; + String? phone; + String? pinType; + String? userRole; + + ResendOtpLoginModel({ + this.username, + this.channelCode, + this.porOrgacode, + this.email, + this.isOtpRequire, + this.phone, + this.pinType, + this.userRole, + }); + + Map toMap() { + final result = {}; + + if (username != null) { + result.addAll({'username': username}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (email != null) { + result.addAll({'email': email}); + } + if (isOtpRequire != null) { + result.addAll({'isOtpRequire': isOtpRequire}); + } + if (phone != null) { + result.addAll({'phone': phone}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + if (userRole != null) { + result.addAll({'userRole': userRole}); + } + + return result; + } + + factory ResendOtpLoginModel.fromMap(Map map) { + return ResendOtpLoginModel( + username: map['username'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + email: map['email'], + isOtpRequire: map['isOtpRequire'], + phone: map['phone'], + pinType: map['pinType'], + userRole: map['userRole'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpLoginModel.fromJson(String source) => + ResendOtpLoginModel.fromMap(json.decode(source)); +} diff --git a/lib/app/models/resend_otp_usend.dart b/lib/app/models/resend_otp_usend.dart new file mode 100644 index 0000000..5eab57d --- /dev/null +++ b/lib/app/models/resend_otp_usend.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; + +class ResendOtpUsendModel { + String? porOrgacode; + String? pctCstycode; + String? channelCode; + String? cmpCustcode; + String? email; + String? pinType; + bool? isOtpRequired; + + ResendOtpUsendModel({ + this.porOrgacode, + this.pctCstycode, + this.channelCode, + this.cmpCustcode, + this.email, + this.pinType, + this.isOtpRequired, + }); + + Map toMap() { + final result = {}; + + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (pctCstycode != null) { + result.addAll({'pctCstycode': pctCstycode}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (cmpCustcode != null) { + result.addAll({'cmpCustcode': cmpCustcode}); + } + if (email != null) { + result.addAll({'email': email}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + if (isOtpRequired != null) { + result.addAll({'isOtpRequired': isOtpRequired}); + } + + return result; + } + + factory ResendOtpUsendModel.fromMap(Map map) { + return ResendOtpUsendModel( + porOrgacode: map['porOrgacode'], + pctCstycode: map['pctCstycode'], + channelCode: map['channelCode'], + cmpCustcode: map['cmpCustcode'], + email: map['email'], + pinType: map['pinType'], + isOtpRequired: map['isOtpRequired'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpUsendModel.fromJson(String source) => + ResendOtpUsendModel.fromMap(json.decode(source)); +} diff --git a/lib/app/models/reverse_transaction_model.dart b/lib/app/models/reverse_transaction_model.dart new file mode 100644 index 0000000..a6dafc8 --- /dev/null +++ b/lib/app/models/reverse_transaction_model.dart @@ -0,0 +1,28 @@ +class ReverseTransactionModel { + String porOrgacode = ""; + String nodeId = ""; + String sgtGntrnumber = ""; + + ReverseTransactionModel({this.porOrgacode = "", this.nodeId = "", this.sgtGntrnumber = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'nodeId': this.nodeId, + 'sgtGntrnumber': this.sgtGntrnumber, + }; + } + + factory ReverseTransactionModel.fromMap(Map map) { + return ReverseTransactionModel( + porOrgacode: map['porOrgacode'] as String, + nodeId: map['nodeId'] as String, + sgtGntrnumber: map['sgtGntrnumber'] as String, + ); + } + + @override + String toString() { + return 'ReverseTransactionModel{porOrgacode: $porOrgacode, nodeId: $nodeId, sgtGntrnumber: $sgtGntrnumber}'; + } +} diff --git a/lib/app/models/u_recived_responce_model.dart b/lib/app/models/u_recived_responce_model.dart new file mode 100644 index 0000000..0a5dcb8 --- /dev/null +++ b/lib/app/models/u_recived_responce_model.dart @@ -0,0 +1,125 @@ +class UReceivedResponseData { + int id = 0; + String porOrgacode = ""; + String drMbmBkmsnumber = ""; + String crMbmBkmsnumber = ""; + String sgtReceiveNodeId = ""; + String sgtSentNodeId = ""; + bool batAcnttranReversed = false; + String dmpProdcode = ""; + String drmbmBkmstitle = ""; + String drpcrCurrdesc = ""; + String cmpCustcode = ""; + String drPcrCurrcode = ""; + String crMbmBkmstitle = ""; + String crPcrCurrdesc = ""; + String crPcrCurrcode = ""; + String sgtSentGntrnumber = ""; + String drSgtGntrdate = ""; + String crSgtGntrdate = ""; + double sgtGntramt = 0.0; + bool batAcnttranSend = false; + bool batAcnttranReceived = false; + String sgtReceiveGntrnumber = ""; + String drPcrCurrshort = ""; + String crPcrCurrshort = ""; + + // String daysToExpire = ""; + String expSgtGntrdate = ""; + + UReceivedResponseData({ + this.id = 0, + this.porOrgacode = "", + this.drMbmBkmsnumber = "", + this.crMbmBkmsnumber = "", + this.sgtReceiveNodeId = "", + this.sgtSentNodeId = "", + this.batAcnttranReversed = false, + this.dmpProdcode = "", + this.drmbmBkmstitle = "", + this.drpcrCurrdesc = "", + this.cmpCustcode = "", + this.drPcrCurrcode = "", + this.crMbmBkmstitle = "", + this.crPcrCurrdesc = "", + this.crPcrCurrcode = "", + this.sgtSentGntrnumber = "", + this.drSgtGntrdate = "", + this.crSgtGntrdate = "", + this.sgtGntramt = 0.0, + this.batAcnttranSend = false, + this.batAcnttranReceived = false, + this.sgtReceiveGntrnumber = "", + this.drPcrCurrshort = "", + this.crPcrCurrshort = "", + // this.daysToExpire = "", + this.expSgtGntrdate = "", + }); + + factory UReceivedResponseData.fromMap(Map map) { + return UReceivedResponseData( + id: map['id'] ?? 0, + porOrgacode: map['porOrgacode'] ?? "", + drMbmBkmsnumber: map['drMbmBkmsnumber'] ?? "", + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + sgtReceiveNodeId: map['sgtReceiveNodeId'] ?? "", + sgtSentNodeId: map['sgtSentNodeId'] ?? "", + batAcnttranReversed: map['batAcnttranReversed'] ?? false, + dmpProdcode: map['dmpProdcode'] ?? "", + drmbmBkmstitle: map['drmbmBkmstitle'] ?? "", + drpcrCurrdesc: map['drpcrCurrdesc'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + drPcrCurrcode: map['drPcrCurrcode'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + sgtSentGntrnumber: map['sgtSentGntrnumber'] ?? "", + drSgtGntrdate: map['drSgtGntrdate'] ?? "", + crSgtGntrdate: map['crSgtGntrdate'] ?? "", + sgtGntramt: map['sgtGntramt'] ?? 0.0, + batAcnttranSend: map['batAcnttranSend'] ?? false, + batAcnttranReceived: map['batAcnttranReceived'] ?? false, + sgtReceiveGntrnumber: map['sgtReceiveGntrnumber'] ?? "", + drPcrCurrshort: map['drPcrCurrshort'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + // daysToExpire: map['daysToExpire'] ?? "", + expSgtGntrdate: map['expSgtGntrdate'] ?? "", + ); + } + + Map toMap() { + return { + 'id': id, + 'porOrgacode': porOrgacode, + 'drMbmBkmsnumber': drMbmBkmsnumber, + 'crMbmBkmsnumber': crMbmBkmsnumber, + 'sgtReceiveNodeId': sgtReceiveNodeId, + 'sgtSentNodeId': sgtSentNodeId, + 'batAcnttranReversed': batAcnttranReversed, + 'dmpProdcode': dmpProdcode, + 'drmbmBkmstitle': drmbmBkmstitle, + 'drpcrCurrdesc': drpcrCurrdesc, + 'cmpCustcode': cmpCustcode, + 'drPcrCurrcode': drPcrCurrcode, + 'crMbmBkmstitle': crMbmBkmstitle, + 'crPcrCurrdesc': crPcrCurrdesc, + 'crPcrCurrcode': crPcrCurrcode, + 'sgtSentGntrnumber': sgtSentGntrnumber, + 'drSgtGntrdate': drSgtGntrdate, + 'crSgtGntrdate': crSgtGntrdate, + 'sgtGntramt': sgtGntramt, + 'batAcnttranSend': batAcnttranSend, + 'batAcnttranReceived': batAcnttranReceived, + 'sgtReceiveGntrnumber': sgtReceiveGntrnumber, + 'drPcrCurrshort': drPcrCurrshort, + 'crPcrCurrshort': crPcrCurrshort, + // 'daysToExpire': daysToExpire, + 'expSgtGntrdate': expSgtGntrdate, + }; + } + + @override + String toString() { + return 'UReceivedResponseData{id: $id, porOrgacode: $porOrgacode, drMbmBkmsnumber: $drMbmBkmsnumber, crMbmBkmsnumber: $crMbmBkmsnumber, sgtReceiveNodeId: $sgtReceiveNodeId, sgtSentNodeId: $sgtSentNodeId, batAcnttranReversed: $batAcnttranReversed, dmpProdcode: $dmpProdcode, drmbmBkmstitle: $drmbmBkmstitle, drpcrCurrdesc: $drpcrCurrdesc, cmpCustcode: $cmpCustcode, drPcrCurrcode: $drPcrCurrcode, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrcode: $crPcrCurrcode, sgtSentGntrnumber: $sgtSentGntrnumber, drSgtGntrdate: $drSgtGntrdate, crSgtGntrdate: $crSgtGntrdate, sgtGntramt: $sgtGntramt, batAcnttranSend: $batAcnttranSend, batAcnttranReceived: $batAcnttranReceived, sgtReceiveGntrnumber: $sgtReceiveGntrnumber, drPcrCurrshort: $drPcrCurrshort, crPcrCurrshort: $crPcrCurrshort, expSgtGntrdate: $expSgtGntrdate}'; + } +} diff --git a/lib/app/models/upload_user_profile_model.dart b/lib/app/models/upload_user_profile_model.dart new file mode 100644 index 0000000..eb9798c --- /dev/null +++ b/lib/app/models/upload_user_profile_model.dart @@ -0,0 +1,28 @@ +class UploadUserProfileModel { + String porOrgacode = ""; + String cmpCustcode = ""; + String cmpCustImage = ""; + + UploadUserProfileModel({this.porOrgacode = "", this.cmpCustcode = "", this.cmpCustImage = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'cmpCustcode': this.cmpCustcode, + 'cmpCustImage': this.cmpCustImage, + }; + } + + factory UploadUserProfileModel.fromMap(Map map) { + return UploadUserProfileModel( + porOrgacode: map['porOrgacode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + cmpCustImage: map['cmpCustImage'] ?? "", + ); + } + + @override + String toString() { + return 'UploadUserProfileModel{porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, cmpCustImage: $cmpCustImage}'; + } +} diff --git a/lib/app/modules/about_us/bindings/about_us_binding.dart b/lib/app/modules/about_us/bindings/about_us_binding.dart new file mode 100644 index 0000000..bb86c54 --- /dev/null +++ b/lib/app/modules/about_us/bindings/about_us_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/about_us_controller.dart'; + +class AboutUsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AboutUsController(), + ); + } +} diff --git a/lib/app/modules/about_us/controllers/about_us_controller.dart b/lib/app/modules/about_us/controllers/about_us_controller.dart new file mode 100644 index 0000000..2e4b3f2 --- /dev/null +++ b/lib/app/modules/about_us/controllers/about_us_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class AboutUsController extends GetxController { + //TODO: Implement AboutUsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/about_us/views/about_us_view.dart b/lib/app/modules/about_us/views/about_us_view.dart new file mode 100644 index 0000000..82281c7 --- /dev/null +++ b/lib/app/modules/about_us/views/about_us_view.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/about_us_controller.dart'; + +class AboutUsView extends GetView { + const AboutUsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAboutUs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHY), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHYDescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHAT), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHATDescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHO), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHODescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text("Version", style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text("1.0.0.3", style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + ); + } +} diff --git a/lib/app/modules/account_statement/bindings/account_statement_binding.dart b/lib/app/modules/account_statement/bindings/account_statement_binding.dart new file mode 100644 index 0000000..5b63d57 --- /dev/null +++ b/lib/app/modules/account_statement/bindings/account_statement_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/account_statement_controller.dart'; + +class AccountStatementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AccountStatementController(), + ); + } +} diff --git a/lib/app/modules/account_statement/controllers/account_statement_controller.dart b/lib/app/modules/account_statement/controllers/account_statement_controller.dart new file mode 100644 index 0000000..03cc80d --- /dev/null +++ b/lib/app/modules/account_statement/controllers/account_statement_controller.dart @@ -0,0 +1,319 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/dialogs/custom_loading.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../custom_widgets/date_picker.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/accountStatementResponseModel.dart'; + +class AccountStatementController extends GetxController { + late InputField depositAccountField; + RxBool isExpanded = false.obs; + bool isCredit = false; + bool isLoading = true; + RxInt selectedIndex = 0.obs; + + late CustomDropDown genderField; + + final AppRepositories repository = Get.find(); + + List accountNumberList = SessionCache.instance.depositAccountList.map((element) => element.mbmBkmsnumber).toList(); + + RxList accountStatement = RxList.empty(); + + RxList allAccountStatement = RxList.empty(); + + ///drop down + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + @override + void onInit() { + super.onInit(); + dp("Deposit List", accountStatement); + + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + + allDepositAccounts.add( + DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + ); + } + + // + } + + @override + Future onReady() async { + super.onReady(); + isLoading = true; + update(); + // showLoader(); + + var accountNumber = Get.arguments; + + dp("Account number", accountNumber); + + Future.delayed(Duration.zero).then((value) { + if (accountNumber != null) { + // + + var selectDepositAcc = allDepositAccounts.firstWhere((e) => (e.data as DepositAccount).mbmBkmsnumber == accountNumber['accountNumber']); + + selectedDepositAccount.value = selectDepositAcc.data; + + depositAccountField.setText(selectDepositAcc.label); + } else { + // + + selectedDepositAccount.value = allDepositAccounts.first.data as DepositAccount; + + depositAccountField.setText(allDepositAccounts.first.label); + } + + fetchAccountStatementTransition(); + }); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + dp("Data update", item); + fetchAccountStatementTransition(); + } + + void addItemToTop(AccountStatementResponseModel newItem) { + accountStatement.insert(0, newItem); + } + + Future fetchAccountStatementTransition() async { + ServerResponse response = await repository.fetchAccountStatement(selectedDepositAccount.value.mbmBkmsnumber); + + if (response.isError) { + Toasty.error(response.errorMsg); + hideLoader(); + isLoading = false; + update(); + return; + } + + List list = List.from(((response.response ?? []) as List).map((x) => AccountStatementResponseModel.fromMap(x))); + + dp("------------------------", list.toString()); + + accountStatement.assignAll(list); + allAccountStatement.assignAll(list); + + hideLoader(); + + isLoading = false; + + update(); + } + + (DateTime, DateTime) weekFirstAndLastDate() { + // Get the current date + DateTime today = DateTime.now(); + +// Define the first day of the week (adjust if needed) + int firstDayOfWeek = MaterialLocalizations.of(Get.context!).firstDayOfWeekIndex; + +// Calculate the offset from today to the first day of the week + int daysOffset = today.weekday - firstDayOfWeek; + +// Handle negative offsets for weeks starting before current day + daysOffset = daysOffset < 0 ? daysOffset + DateTime.daysPerWeek : daysOffset; + +// Get the first date of the current week + DateTime firstDate = today.subtract(Duration(days: daysOffset)); + +// Get the last date of the current week + DateTime lastDate = firstDate.add(const Duration(days: DateTime.daysPerWeek - 1)); + +// Now you have both firstDate and lastDate representing the current week + return (firstDate, lastDate); + } + + (DateTime, DateTime) monthFirstAndLastDate() { + // + + DateTime today = DateTime.now(); + +// Get the year + int year = today.year; + +// Get the month + int month = today.month; + +// Create the first date of the month + DateTime firstDate = DateTime(year, month, 1); + +// Get the last day of the month (tricky part) + DateTime lastDate = DateTime(year, month + 1, 0); + return (firstDate, lastDate); + } + + var currentDate = DateTime.now(); + + // void updateRange(int i) { + // dp("Current selected", i); + // selectedIndex.value = i; + // accountStatement.assignAll(allAccountStatement); + // + // if (i == 1) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return DateTime(date.year, date.month, date.day) == DateTime(currentDate.year, currentDate.month, currentDate.day); + // }).toList(); + // } + // if (i == 2) { + // // + // + // var weekDate = weekFirstAndLastDate(); + // + // dp("Week date", weekDate); + // + // accountStatement.value = accountStatement.where((e) => DateTime.parse(e.drSgtGntrdate).isAfter(weekDate.$1) && DateTime.parse(e.drSgtGntrdate).isBefore(weekDate.$2)).toList(); + // } + // if (i == 3) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return date.month == currentDate.month && date.year == currentDate.year; + // }).toList(); + // } + // if (i == 4) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return date.year == currentDate.year; + // }).toList(); + // } + // } + void updateRange(int i) { + dp("Current selected", i); + selectedIndex.value = i; + accountStatement.assignAll(allAccountStatement); + + /// Check All Transactions + if (i == 1) { + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Date 1", date); + return DateTime(date.year, date.month, date.day) == DateTime(currentDate.year, currentDate.month, currentDate.day); + }).toList(); + } + + /// Check Week Transactions + if (i == 2) { + var weekDate = weekFirstAndLastDate(); + dp("Week date", weekDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + return date.isAfter(weekDate.$1.subtract(const Duration(days: 1))) && date.isBefore(weekDate.$2.add(const Duration(days: 1))); + }).toList(); + } + + /// Month wise Transactions + if (i == 3) { + var monthDate = monthFirstAndLastDate(); + dp("Month date", monthDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + return date.isAfter(monthDate.$1.subtract(const Duration(days: 1))) && date.isBefore(monthDate.$2.add(const Duration(days: 1))); + }).toList(); + } + + /// Yearly Transaction + if (i == 4) { + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Date 1", date); + return date.year == currentDate.year; + }).toList(); + } + } + // void showDateRangePic() async { + // // + // accountStatement.assignAll(allAccountStatement); + // + // var range = await DatePicker.showRangeDatePicker(); + // + // dp("Date range", range?[0]); + // + // dp("Date range", range?[1]); + // + // if (range == null || range.isEmpty) { + // // Toasty.error("Range is not selected"); + // return; + // } + // + // var firstDate = DateTime(range[0]!.year, range[0]!.month, range[0]!.day, 24, 0, 0, 0); + // + // var lastDate = DateTime(range[1]!.year, range[1]!.month, range[1]!.day, 23, 0, 0, 0); + // + // dp("Las date", lastDate); + // + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // + // dp("Date 1", date); + // + // return date.isAfter(firstDate) && date.isBefore(lastDate); + // }).toList(); + // } + + void showDateRangePic() async { + accountStatement.assignAll(allAccountStatement); + + var range = await DatePicker.showRangeDatePicker(); + + if (range == null) { + // User clicked Cancel, do nothing + return; + } + + if (range.isEmpty || range.length != 2 || range[0] == null || range[1] == null) { + // Show error message if the range is not properly selected + Toasty.error("Please select both start and end dates."); + return; + } + + dp("Date range", range[0]); + dp("Date range", range[1]); + + var firstDate = DateTime(range[0]!.year, range[0]!.month, range[0]!.day, 0, 0, 0, 0); + var lastDate = DateTime(range[1]!.year, range[1]!.month, range[1]!.day, 23, 59, 59, 999); + + + // var currentDate = DateTime.now(); + // if (lastDate.isAfter(currentDate) || !lastDate.isAtSameMomentAs(currentDate)) { + // // Show error message if the to date is after the current date (excluding current date) + // Toasty.error("Please select a date range up to the current date."); + // return; + // } + + + dp("First date", firstDate); + dp("Last date", lastDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Transaction date", date); + return date.isAfter(firstDate.subtract(Duration(milliseconds: 1))) && date.isBefore(lastDate.add(Duration(milliseconds: 1))); + }).toList(); + } + + +} diff --git a/lib/app/modules/account_statement/views/account_statement_view.dart b/lib/app/modules/account_statement/views/account_statement_view.dart new file mode 100644 index 0000000..8388b4e --- /dev/null +++ b/lib/app/modules/account_statement/views/account_statement_view.dart @@ -0,0 +1,145 @@ +import 'package:animated_toggle_switch/animated_toggle_switch.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/account_statement/views/shared/account_Statement_widget.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/account_statement_controller.dart'; + +class AccountStatementView extends GetView { + const AccountStatementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + inputColor: Colors.black, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textStatementDetails, + ), + style: Theme.of(context).textTheme.titleSmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 15), + Row( + children: [ + Expanded( + flex: 10, + child: AnimatedToggleSwitch.size( + height: 30, + current: controller.selectedIndex.value, + style: ToggleStyle( + backgroundColor: AppColors.colorGrey350, + indicatorColor: AppColors.white, + borderColor: Colors.transparent, + borderRadius: BorderRadius.circular(10.0), + indicatorBorderRadius: const BorderRadius.only(topRight: Radius.circular(8.0), topLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0)), + ), + values: const [0, 1, 2, 3], + iconOpacity: 1.0, + selectedIconScale: 1.0, + indicatorSize: const Size.fromWidth(double.infinity), + iconAnimationType: AnimationType.onHover, + styleAnimationType: AnimationType.onHover, + spacing: 10.0, + customSeparatorBuilder: (context, local, global) { + final opacity = ((global.position - local.position).abs() - 0.5).clamp(0.0, 1.0); + return VerticalDivider( + indent: 10.0, + endIndent: 10.0, + color: Colors.white38.withOpacity(opacity), + ); + }, + customIconBuilder: (context, local, global) { + final text = const ['ALL', 'D', 'W', 'M', 'Y'][local.index]; + return Center( + child: Text( + text, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w400, + color: Color.lerp(Colors.black, AppColors.black, local.animationValue), + ), + ), + ); + }, + borderWidth: 0.0, + onChanged: (i) { + controller.updateRange(i); + }, + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () { + controller.showDateRangePic(); + }, + child: Container( + height: 30, + width: 30, + padding: const EdgeInsets.all(7.0), + decoration: const BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.only(topRight: Radius.circular(8.0), topLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0)), + ), + child: SvgPicture.asset(AppAssets.ic_filter_statement), + ), + ), + ], + ), + const SizedBox(height: 15), + controller.accountStatement.isNotEmpty + ? Expanded( + child: ListView.builder( + itemCount: controller.accountStatement.length, + itemBuilder: (context, index) { + return AccountStatementWidget( + onTap: () {}, + statment: controller.accountStatement[index], + ); + }, + ), + ) + : const Center( + child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), + ), + ], + ), + ); + })); + } +} diff --git a/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart b/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart new file mode 100644 index 0000000..d150f36 --- /dev/null +++ b/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../../models/accountStatementResponseModel.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/account_statement_controller.dart'; + +class AccountStatementWidget extends StatefulWidget { + // bool isCredit = false; + // String transactionAmount = ""; + // String transactionDate = ""; + // String accountBalance = ""; + // String transactionDetail = ""; + final AccountStatementResponseModel statment; + final Function()? onTap; + + const AccountStatementWidget({ + Key? key, + required this.statment, + this.onTap, + }) : super(key: key); + + @override + State createState() => _AccountStatementWidgetState(); +} + +class _AccountStatementWidgetState extends State { + // + + AccountStatementController accountStatementController = Get.find(); + + bool isExpanded = false; + + bool isDr(AccountStatementResponseModel statment) { + if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return true; + } else { + return false; + } + } + + IconData statementIcon(AccountStatementResponseModel statment) { + if (statment.batAcnttranReversed) { + return Icons.redo; + } else if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return Icons.arrow_upward_outlined; + } else { + return Icons.arrow_downward_outlined; + } + } + + Color statementColor(AccountStatementResponseModel statment) { + if (statment.batAcnttranReversed) { + return AppColors.colorGrey400; + } else if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return AppColors.red; + } else { + return AppColors.colorButton; + } + } + @override + Widget build(BuildContext context) { + var statment = widget.statment; + return InkWell( + onTap: widget.onTap, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 3.0), + child: Card( + color: Colors.white, + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + child: ExpansionTile( + dense: false, + onExpansionChanged: (value) { + // accountStatementController.toggleExpansion(value); + isExpanded = value; + setState(() {}); + }, + maintainState: true, + //expandedAlignment: Alignment.topLeft, + expandedCrossAxisAlignment: CrossAxisAlignment.start, + childrenPadding: const EdgeInsets.only(left: 12, right: 10, bottom: 10), + tilePadding: const EdgeInsets.all(8.0), + collapsedShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + collapsedBackgroundColor: AppColors.white, + shape: const Border(), + backgroundColor: AppColors.white, + expandedAlignment: Alignment.centerLeft, + leading: SizedBox( + height: 35, + width: 35, + child: CircleAvatar(backgroundColor: statementColor(statment) /*colorPrimary.withOpacity(0.7)*/, child: Padding(padding: EdgeInsets.all(2.0), child: Icon(color: AppColors.white, statementIcon(statment)))), + ), + trailing: isExpanded + ? const SizedBox() + : Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text("${statment.drPcrCurrshort} ${statment.sgtGntramt}", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("${isDr(statment) ? statment.drPcrCurrshort : statment.crPcrCurrshort} ${isDr(statment) ? statment.drMbmBkmsbalance : statment.crMbmBkmsbalance}", style: Theme.of(context).textTheme.bodySmall), + ], + ), + title: isExpanded + ? const SizedBox() + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(isDr(statment) ? statment.crMbmBkmstitle.toString() : statment.drmbmBkmstitle.toString(), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(statment.drSgtGntrdate.toString().isEmpty ? "0" : statment.drSgtGntrdate.toString(), style: Theme.of(context).textTheme.bodySmall), + ], + ), + children: [ + Text("Amount: ${statment.drPcrCurrshort} ${statment.sgtGntramt.toString()}", style: Theme.of(context).textTheme.labelMedium!.copyWith(fontSize: 14, color: AppColors.colorTitle)), + const SizedBox(height: 5), + Text("Transaction-ID: ${statment.sgtSentGntrnumber.toString()}${statment.sgtSentNodeId}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Date: ${statment.drSgtGntrdate.toString().isEmpty ? "0" : statment.drSgtGntrdate.toString()}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("${isDr(statment) ? "Receiver: " : "Sender: "} ${isDr(statment) ? statment.crMbmBkmstitle : statment.drmbmBkmstitle}", style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 3), + Text("Running-Balance: ${isDr(statment) ? statment.drPcrCurrshort : statment.crPcrCurrshort} ${isDr(statment) ? statment.drMbmBkmsbalance : statment.crMbmBkmsbalance}", style: Theme.of(context).textTheme.labelMedium!.copyWith(color: AppColors.colorTitle)), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/add_money_binding.dart b/lib/app/modules/add_money/bindings/add_money_binding.dart new file mode 100644 index 0000000..c542028 --- /dev/null +++ b/lib/app/modules/add_money/bindings/add_money_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/add_money_controller.dart'; + +class AddMoneyBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddMoneyController(), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/add_money_otp_binding.dart b/lib/app/modules/add_money/bindings/add_money_otp_binding.dart new file mode 100644 index 0000000..941d958 --- /dev/null +++ b/lib/app/modules/add_money/bindings/add_money_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/add_money_otp_controller.dart'; + + +class AddMoneyOTPBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddMoneyOTPController(), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/payment_method_binding.dart b/lib/app/modules/add_money/bindings/payment_method_binding.dart new file mode 100644 index 0000000..0e4357b --- /dev/null +++ b/lib/app/modules/add_money/bindings/payment_method_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/payment_method_controller.dart'; + + +class PaymentMethodBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => PaymentMethodController(), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/add_money/controllers/add_money_controller.dart b/lib/app/modules/add_money/controllers/add_money_controller.dart new file mode 100644 index 0000000..26a434f --- /dev/null +++ b/lib/app/modules/add_money/controllers/add_money_controller.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/controllers/payment_method_controller.dart'; + + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/evaluated_cuency_model.dart'; +import '../../../models/product_model.dart'; +import '../../../routes/app_pages.dart'; +import '../views/shared/account_list_screen.dart'; + +class AddMoneyController extends GetxController { + final repository = Get.find(); + var paymnetController = Get.put(PaymentMethodController()); + TextEditingController recipientController = TextEditingController(); + TextEditingController pinPutController = TextEditingController(); + + Rx selectRecepientAccount = Rx(DepositAccount.empty()); + + List currencyList = []; + List allCurrencyList = []; + Rx selectedFromAccountCurrency = Rx(ProductDepositModel(porOrgacode: "", dmpProdcode: "", dmpProddesc: "", dmpProdshort: "", pcrCurrcode: "", dmpProdactive: false)); + + Rx evaluatedCurrencyModel = EvaluatedCurrencyModel.empty().obs; + + late InputField amountFeild; + + // late InputField convertedFeild; + + late InputField searchCurrency; + + late InputField searchAccount; + + List accountList = List.from(SessionCache.instance.depositAccountList); + + List allAccountList = List.from(SessionCache.instance.depositAccountList); + + @override + void onInit() { + getCurrencyList(); + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + + update(); + + amountFeild.clear(); + } + + @override + void dispose() { + amountFeild.clear(); + super.dispose(); + } + + searchCurrencyM() { + Future.delayed(const Duration(seconds: 1)).then( + (value) { + searchCurrency.clear(); + update(); + searchCurrency.controller!.addListener( + () { + searchCurrencyMethod(); + }, + ); + }, + ); + } + + searchAccountInit() { + Future.delayed(const Duration(seconds: 1)).then( + (value) { + searchAccount.clear(); + update(); + searchAccount.controller!.addListener( + () { + searchAccountMethod(); + }, + ); + }, + ); + } + + void updateReceipentAccount(DepositAccount e) { + selectRecepientAccount.value = e; + update(); + } + + void updateFromAccountCurrency(ProductDepositModel fromAccountCurrecncy) { + selectedFromAccountCurrency.value = fromAccountCurrecncy; + update(); + } + + void showDialog(BuildContext context) { + CustomDialog.showSuccessDialog( + description: "Thank you so much, your payment has been added.", + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.DASHBOARD_SCREEN); + }); + } + + String getFlagWithCurrencyCode(String currencyCode) { + int currencyCodeInt = int.tryParse(currencyCode) ?? 0; + + if (currencyCodeInt == 586) { + return "assets/uco/icons/ic_pakistan.png"; + } else if (currencyCodeInt == 997) { + return "assets/uco/icons/usa.png"; + } else if (currencyCodeInt == 978) { + return "assets/uco/icons/euro_flag.png"; + } else { + return ""; + } + } + + getConversionAmount() async { + if (!validate()) { + return; + } + + if (selectRecepientAccount.value.pcrCurrcode.isEmpty) { + // Toasty.error("Please select recipient currency"); + return; + } + + var converionResponce = await repository.getConvertedCurrency( + selectedFromAccountCurrency.value.pcrCurrcode, + selectRecepientAccount.value.pcrCurrcode, + amountFeild.getCustomText(), + ); + + if (converionResponce.isError) { + Toasty.error(converionResponce.errorMsg); + return; + } + evaluatedCurrencyModel.value = EvaluatedCurrencyModel.fromMap(converionResponce.response); + recipientController.text = evaluatedCurrencyModel.value.sgtGntramtfc.toStringAsFixed(2); + } + + getCurrencyList() async { + // + var responce = await repository.getCurrencyList(); + if (responce.isError) { + Toasty.error(responce.errorMsg); + return; + } + currencyList = ProductDepositModel.productListFromJson(responce.response); + allCurrencyList.addAll(currencyList); + selectedFromAccountCurrency.value = currencyList.first; + + selectRecepientAccount.value = accountList.first; + update(); + } + + bool validate() { + if (selectRecepientAccount.value.pcrCurrcode.isEmpty || paymnetController.paymentMethod.value.title.isEmpty || paymnetController.paymentMethod.value.title.isEmpty) { + return false; + } + return FieldValidation.validateAll([amountFeild]); + } + + bool checkForNull() { + if (evaluatedCurrencyModel.value.pcrCurrcode == null || evaluatedCurrencyModel.value.serviceCharges == null || evaluatedCurrencyModel.value.sgtGntramtfc == null || evaluatedCurrencyModel.value.targetPerEratrateact == null) { + return true; + } + return false; + } + + Future navigateToNextScreen() async { + // if (!validate()) { + // if (amountFeild.getCustomText().trim().isEmpty) { + // Toasty.error("Please Input amount and then proceed"); + // return; + // } + // if (paymnetController.paymentMethod.value.title.isEmpty) { + // Toasty.error("Please select payment method and then proceed"); + // return; + // } + // } + await getConversionAmount(); + // GLACCAddMoneyRequestModel requestModel = GLACCAddMoneyRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drPcaGlaccode: "", + // drPcaGlacdesc: "", + // crMbmBkmsnumber: selectRecepientAccount.value.mbmBkmsnumber, + // crMbmBkmstitle: selectRecepientAccount.value.mbmBkmstitle, + // crPcrCurrcode: selectRecepientAccount.value.pcrCurrcode, + // crPcrCurrdesc: selectRecepientAccount.value.pcrCurrdesc, + // crPcrCurrshort: selectRecepientAccount.value.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectRecepientAccount.value.dmpProdcode, + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(recipientController.text.isEmpty ? "0.0" : recipientController.text), + // otdTrancomment: "", + // obpPincode: "", + // transType: "", + // pinType: "", + // ); + + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + + Get.toNamed( + Routes.GENERAL_LEDGER, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: requestModel, + // AppConstants.EXCHANGE_RATE: evaluatedCurrencyModel.value, + // }, + ); + } + + void selectFromAccountCurrency() { + Get.to(() => AccountListScreen())!.then( + (value) { + getConversionAmount(); + }, + ); + } + + void searchCurrencyMethod() async { + var search = searchCurrency.getCustomText().toLowerCase(); + currencyList.clear(); + update(); + // await Future.delayed(Duration(milliseconds: 100)); + if (search.isNotEmpty) { + currencyList = allCurrencyList + .where( + (element) => element.dmpProddesc.toLowerCase().contains(search) || element.dmpProdshort.toLowerCase().contains(search) || element.dmpProddesc.toLowerCase().contains(search), + ) + .toList(); + } else { + currencyList.addAll(allCurrencyList); + } + + update(); + } + + void searchAccountMethod() async { + // + + var accountText = searchAccount.getCustomText().toLowerCase(); + + accountList.clear(); + + update(); + + if (accountText.isNotEmpty) { + // + + accountList = allAccountList + .where( + (element) => element.mbmBkmsnumber.toLowerCase().contains(accountText) || element.dmpProddesc.toLowerCase().contains(accountText) || element.pcrCurrcode.toLowerCase().contains(accountText) || element.mbmBkmstitle.toLowerCase().contains(accountText), + ) + .toList(); + } else { + accountList.addAll(allAccountList); + } + + update(); + } +} diff --git a/lib/app/modules/add_money/controllers/add_money_otp_controller.dart b/lib/app/modules/add_money/controllers/add_money_otp_controller.dart new file mode 100644 index 0000000..e2301fb --- /dev/null +++ b/lib/app/modules/add_money/controllers/add_money_otp_controller.dart @@ -0,0 +1,91 @@ +import 'package:flutter/cupertino.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../routes/app_pages.dart'; +import '../../general_ledger/controllers/general_ledger_controller.dart'; + + +class AddMoneyOTPController extends GetxController { + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + + RxBool isResend = false.obs; + + CountdownController countdownController = + CountdownController(autoStart: true); + + // GLACCAddMoneyRequestModel transactionSubmitRequestModel = + // GLACCAddMoneyRequestModel.empty(); + // Rx evaluatedCurrencyModel = + // EvaluatedCurrencyModel.empty().obs; + + // @override + // void onInit() { + // super.onInit(); + // var arguments = Get.arguments; + // transactionSubmitRequestModel = (arguments != null + // ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? + // GLACCAddMoneyRequestModel.empty() + // : GLACCAddMoneyRequestModel.empty()); + // evaluatedCurrencyModel.value = (arguments != null + // ? arguments[AppConstants.EXCHANGE_RATE] ?? + // EvaluatedCurrencyModel.empty() + // : EvaluatedCurrencyModel.empty()); + // } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + // transactionSubmitRequestModel + // transactionSubmitRequestModel.pinType = "TRAN"; + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + sendTransaction(); + } + + Future sendTransaction() async { + // ServerResponse response = + // await repository.sendAddMoneyTransaction(transactionSubmitRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + Get.find().clearAll(); + + + + CustomDialog.showSuccessDialog( + title: "Congratulations!", + description: "Thank you so much, your payment has been added.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }); + } + + void resenOtp() async { + // + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + isResend.value = false; + countdownController.restart(); + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/add_money/controllers/payment_method_controller.dart b/lib/app/modules/add_money/controllers/payment_method_controller.dart new file mode 100644 index 0000000..aa5141d --- /dev/null +++ b/lib/app/modules/add_money/controllers/payment_method_controller.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../res/app_colors.dart'; + + +class PaymentMethodController extends GetxController { + List paymentList = [ + PaymentMethod( + title: "Debit Card", + image: AppAssets.ic_debit_card, + content: + "10.78 GBP fee, so recipient gets 340839.71 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + PaymentMethod( + title: "Credit Card", + image: AppAssets.ic_debit_card, + content: + "10.78 GBP fee, so recipient gets 340839.71 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + PaymentMethod( + title: "Bank Transfer", + image: AppAssets.ic_bank, + content: + "6.63 GBP fee, so recipient gets 342269.61 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + ]; + + Rx paymentMethod = Rx( + PaymentMethod(image: "", title: "", content: "", icon: Icon(Icons.abc))); + + updatePaymentMethod(PaymentMethod p) { + paymentMethod.value = p; + Get.back(); + } +} + +class PaymentMethod { + String title; + String content; + Icon icon; + String image; + + PaymentMethod( + {required this.image, + required this.title, + required this.content, + required this.icon}); +} diff --git a/lib/app/modules/add_money/views/add_money_view.dart b/lib/app/modules/add_money/views/add_money_view.dart new file mode 100644 index 0000000..c07d23b --- /dev/null +++ b/lib/app/modules/add_money/views/add_money_view.dart @@ -0,0 +1,278 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/views/shared/currency_list_screen.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/views/shared/payment_method_view.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_theme.dart'; +import '../controllers/add_money_controller.dart'; + +class AddMoneyView extends GetView { + const AddMoneyView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: DashBoardAppBar( + title: "Add Money", + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + child: CustomButton( + onPressed: () { + controller.navigateToNextScreen(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + body: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + child: SingleChildScrollView( + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text("You send exactly"), + const SizedBox(height: 8), + controller.amountFeild = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}amountFeild"), + controller: FormFieldConstants.instance().getController("${className}amountFeild"), + hintText: "Enter amount", + radius: 10, + inputFontSize: 20.0, + inputColor: AppColors.black, + inputFontWeight: FontWeight.w600, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + isTopMarginRequired: false, + showLabel: false, + textInputAction: TextInputAction.done, + onChanged: (value) { + Future.delayed(const Duration(milliseconds: 500), () => controller.getConversionAmount()); + }, + onSubmitted: (value) { + controller.getConversionAmount(); + }, + suffixIcon: GestureDetector( + onTap: () { + controller.selectFromAccountCurrency(); + }, + child: Container( + color: AppColors.transparent, + child: SizedBox( + width: 130, + height: 60, + child: Row( + children: [ + // Image.asset(controller.getFlagWithCurrencyCode(controller.selectedFromAccountCurrency.value.pcrCurrcode), width: 22), + // const SizedBox(width: 6), + // Text( + // controller.selectedFromAccountCurrency.value.dmpProdshort, + // style: context.textTheme.bodyMedium!.copyWith(fontSize: 16, color: AppColors.colorPrimary, fontWeight: FontWeight.w600), + // ), + const SizedBox(width: 105), + Image.asset(AppAssets.drop_down_ic, width: 10, height: 10), + const SizedBox(width: 6), + ], + ), + ), + ), + ), + ), + const SizedBox(height: 17), + Text( + "Paying with", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + const SizedBox(height: 8), + InkWell( + onTap: () { + Get.to(() => const PaymentMethodView())!.then( + (value) { + controller.getConversionAmount(); + }, + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: AppColors.colorGrey200, + ), + padding: const EdgeInsets.only(left: 13, top: 17, bottom: 17, right: 15), + child: Row( + children: [ + Text( + controller.paymnetController.paymentMethod.value.title.isNotEmpty ? TranslationKeys.makeTranslation(controller.paymnetController.paymentMethod.value.title) : "Select a payment method", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.F0F0D), + ), + const Spacer(), + Card( + elevation: 0.0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50), side: BorderSide(color: AppColors.CFCFCF)), + child: Padding( + padding: const EdgeInsets.only( + left: 15, + right: 15, + top: 5, + bottom: 5, + ), + child: Center( + child: Text( + "Select", + style: context.textTheme.bodyLarge!.copyWith(fontSize: 11, fontWeight: FontWeight.w500), + ), + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 17), + Text( + "Recipient Get", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + const SizedBox(height: 8), + Container( + height: 60, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: const BorderRadius.all(Radius.circular(10)), + border: Border.all(color: AppColors.colorGrey500, width: 1.5), + ), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 4, + child: TextField( + style: AppThemeData.inputStyle.copyWith(height: 1, fontSize: 20.0, fontWeight: FontWeight.w600, color: AppColors.black), + controller: controller.recipientController, + decoration: const InputDecoration(border: InputBorder.none), + enabled: false, + ), + ), + GestureDetector( + onTap: () { + Get.to(() => CurrencyListScreen())!.then( + (value) { + controller.getConversionAmount(); + }, + ); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + Image.asset( + controller.getFlagWithCurrencyCode(controller.selectRecepientAccount.value.pcrCurrcode), + width: 22, + errorBuilder: (context, error, stackTrace) => const SizedBox(), + ), + const SizedBox(width: 6), + Text(controller.selectRecepientAccount.value.pcrCurrshort, style: context.textTheme.bodyMedium!.copyWith(fontSize: 16, color: AppColors.colorPrimary, fontWeight: FontWeight.w500)), + const SizedBox(width: 6), + Image.asset(AppAssets.drop_down_ic, width: 10, height: 10), + const SizedBox(width: 15), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 15), + ...(controller.checkForNull()) + ? [] + : [ + detailsTile(controller.evaluatedCurrencyModel.value.serviceCharges.toString(), "Our fee"), + + detailsTile(controller.evaluatedCurrencyModel.value.sgtGntramtfc!.toString(), "Total amount we’ll convert"), + + //{"title": "344.598", "subtitle": ""}, + detailsTile( + controller.evaluatedCurrencyModel.value.targetPerEratrateact.toString(), + "Guaranteed exchange rate (2h)", + subTitleStyle: Get.context?.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorPrimary, decoration: TextDecoration.underline), + ), + const SizedBox(height: 35), + Text( + "Usually arrives in seconds. Because this is your first transfer, things may take a little longer.", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 15, + fontWeight: FontWeight.w400, + ), + ), + const SizedBox(height: 20), + ], + ], + ); + }), + ), + ), + ); + } + + Widget detailsTile(String title, String subTitle, {TextStyle? subTitleStyle}) { + return Padding( + padding: const EdgeInsets.only(top: 20), + child: Row( + children: [ + Container( + width: 13, + height: 13, + decoration: BoxDecoration(color: AppColors.colorTitle, borderRadius: BorderRadius.circular(20)), + ), + const SizedBox(width: 6), + Text( + title, + style: Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w700, + ), + ), + const Spacer(), + Text( + subTitle, + style: subTitleStyle ?? + Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ); + } +} + +showCurrencyBtm() { + Get.bottomSheet( + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorGrey800, width: 1), borderRadius: const BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: const Text("data"), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} diff --git a/lib/app/modules/add_money/views/shared/account_list_screen.dart b/lib/app/modules/add_money/views/shared/account_list_screen.dart new file mode 100644 index 0000000..5209a72 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/account_list_screen.dart @@ -0,0 +1,118 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/form_field_constants.dart'; +import '../../../../custom_widgets/Fields/input_field.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/add_money_controller.dart'; + +class AccountListScreen extends StatefulWidget { + AccountListScreen({super.key}); + + @override + State createState() => _AccountListScreenState(); +} + +class _AccountListScreenState extends State { + @override + void initState() { + Get.find().searchAccountInit(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 20, + ), + child: GetBuilder(builder: (controller) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose account", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.titleColor), + ), + const SizedBox(height: 8), + const Divider(color: Colors.grey), + const SizedBox(height: 8), + controller.searchAccount = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}searchAccount"), + controller: FormFieldConstants.instance().getController("${className}searchAccount"), + hintText: "Search for a account", + prefixIcon: const Icon(Icons.search), + isDropDown: false, + showLabel: false, + isTopMarginRequired: false, + ), + const SizedBox(height: 8), + const Divider(color: Colors.grey), + const SizedBox(height: 8), + ...controller.currencyList + .map((e) => InkWell( + onTap: () { + controller.updateFromAccountCurrency(e); + Get.back(); + }, + child: currencyTile(e.dmpProdshort, "${e.dmpProddesc} (${e.dmpProdcode})", controller.getFlagWithCurrencyCode(e.pcrCurrcode)))) + .toList(), + ], + ); + }), + ), + ), + ), + ); + } + + Widget currencyTile(String title, String subTitle, String flag) { + return Padding( + padding: const EdgeInsets.only(top: 0), + child: SizedBox( + height: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + flag, + height: 40, + width: 40, + ), + const SizedBox(width: 12), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 2), + Text( + subTitle, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/currency_list_screen.dart b/lib/app/modules/add_money/views/shared/currency_list_screen.dart new file mode 100644 index 0000000..918f31e --- /dev/null +++ b/lib/app/modules/add_money/views/shared/currency_list_screen.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/form_field_constants.dart'; +import '../../../../core/utils/logs_utils.dart'; +import '../../../../custom_widgets/Fields/input_field.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/add_money_controller.dart'; + +class CurrencyListScreen extends StatefulWidget { + CurrencyListScreen({super.key}); + + @override + State createState() => _CurrencyListScreenState(); +} + +class _CurrencyListScreenState extends State { + + @override + void initState() { + Get.find().searchCurrencyM(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: GetBuilder(builder: (controller) { + return Padding( + padding: const EdgeInsets.only( + left: 20, + right: 30, + top: 20, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose a currency", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 18, + fontWeight: FontWeight.w500, + color: AppColors.titleColor), + ), + const SizedBox(height: 14), + controller.searchCurrency = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}searchCurrency"), + controller: FormFieldConstants.instance() + .getController("${className}searchCurrency"), + hintText: "Search for a currency / country", + prefixIcon: const Icon(Icons.search), + isDropDown: false, + showLabel: false, + isTopMarginRequired: false, + ), + const SizedBox(height: 18), + Text( + "Popular currencies", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w400, + color: AppColors.colorTitle, + ), + ), + const Divider(color: Colors.grey), + ...controller.allAccountList + .map((e) => InkWell( + onTap: () { + dp("Click popular", "arg"); + controller.updateReceipentAccount(e); + Get.back(); + }, + child: currencyTile( + e.mbmBkmstitle, e.dmpProddesc, e.pcrCurrcode))) + .toList(), + ], + ), + ); + }), + ), + ); + } + + Widget currencyTile(String title, String subTitle, String flag) { + return Padding( + padding: const EdgeInsets.only(top: 0), + child: SizedBox( + height: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + Get.find().getFlagWithCurrencyCode(flag), + height: 40, + width: 40, + ), + const SizedBox(width: 12), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Get.context!.textTheme.bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 2), + Text( + subTitle, + style: Get.context!.textTheme.bodyMedium! + .copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/otp_add_money.dart b/lib/app/modules/add_money/views/shared/otp_add_money.dart new file mode 100644 index 0000000..7bf1801 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/otp_add_money.dart @@ -0,0 +1,155 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../custom_widgets/custom_button.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../res/app_dimensions.dart'; +import '../../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../controllers/add_money_otp_controller.dart'; + +class AddMoneyOTPView extends GetView { + const AddMoneyOTPView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: AppDimensions.screenHorizontalPadding, + vertical: AppDimensions.screenVerticalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOTPDescription), + style: + Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + textInputAction: TextInputAction.done, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOTPValid), + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, + height: 20, width: 20), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value + ? AppColors.colorPrimary + : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/payment_method_view.dart b/lib/app/modules/add_money/views/shared/payment_method_view.dart new file mode 100644 index 0000000..4025311 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/payment_method_view.dart @@ -0,0 +1,191 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/payment_method_controller.dart'; + + +class PaymentMethodView extends GetView { + const PaymentMethodView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textHowdoyouwanttopay), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.black)), + const SizedBox(height: 30), + Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_debit_card), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCard), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + const SizedBox(height: 30), + Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_debit_card), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textCreditCard), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + const SizedBox(height: 30), + InkWell( + onTap: () {}, + child: Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_bank_transfer), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBankTransfer), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + ), + const SizedBox(height: 40), + Container(height: 1, width: double.infinity, color: AppColors.colorGrey350), + const SizedBox(height: 40), + InkWell( + onTap: () { + controller.updatePaymentMethod(PaymentMethod(image: AppAssets.ic_general_ledger, title: TranslationKeys.textGeneralLedger, content: "", icon: const Icon(Icons.abc))); + }, + child: Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_general_ledger), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textGeneralLedger), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/add_new_account/bindings/add_new_binding.dart b/lib/app/modules/add_new_account/bindings/add_new_binding.dart new file mode 100644 index 0000000..3e26b26 --- /dev/null +++ b/lib/app/modules/add_new_account/bindings/add_new_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/add_new_account_controller.dart'; + +class AddNewAccountBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddNewAccountController(), + ); + } +} diff --git a/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart b/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart new file mode 100644 index 0000000..9e0a8ad --- /dev/null +++ b/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/product_model.dart'; +import '../../../routes/app_pages.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + + +class AddNewAccountController extends GetxController { + BuildContext context = Get.context as BuildContext; + + late InputField currencyCodesField; + late InputField nameAddressField; + + DropDown dropDownValue = DropDown.empty(); + + List currencyList = []; + + List currencyListDropDown = []; + + final AppRepositories repository = Get.find(); + + void updateCurrency(DropDown? item) { + dropDownValue = item!; + update(); + } + + @override + void onInit() { + super.onInit(); + // getCurrencyList(); + } + + /// Validate Function of contorller + // bool validate() { + // bool isValid = FieldValidation.validateAll([nameAddressField, currencyCodesField]); + // return isValid; + // } + + /// Get Currency List Function + getCurrencyList() async { + try { + var productResponse = await repository.getCurrencyList(); + // + // if (productResponse.isError) { + // Toasty.error(productResponse.errorMsg); + // return; + // } + // + // currencyList = ProductDepositModel.productListFromJson(productResponse.response); + // + // currencyListDropDown = currencyList.map((e) => DropDown(e.dmpProdcode, e.dmpProddesc, e)).toList(); + // + // dropDownValue = currencyListDropDown.first; + // + // dp("DmpProductCode", currencyListDropDown); + + update(); + } catch (e, s) { + dp("Error in get product $e", s); + Toasty.error("Something went wrong, please try again"); + } + } + + /// New Create Account Request Function + void validateAndSendRequest() async { + // + + hideKeyBoard(); + + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // AddNewAccountRequestModel request = AddNewAccountRequestModel( + // title: nameAddressField.getCustomText(), + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // channelCode: SessionCache.instance.userInfo.channelCode, + // dmpProdcode: dropDownValue.id, + // email: SessionCache.instance.userInfo.cmpUserId, + // ); + // + // ServerResponse response = await repository.addNewAccount(request); + // + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + CustomDialog.showSuccessDialog( + description: "Thank you so much, Your new account has been created successfully", + onTapPositive: () { + transitionUpdate.value++; + + Navigator.of(context, rootNavigator: true).pop(); + + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }); + + clearText(); + } + + /// Clear Controller Function + clearText() { + nameAddressField.clear(); + currencyCodesField.clear(); + update(); + } +} diff --git a/lib/app/modules/add_new_account/views/add_new_account_view.dart b/lib/app/modules/add_new_account/views/add_new_account_view.dart new file mode 100644 index 0000000..427ce87 --- /dev/null +++ b/lib/app/modules/add_new_account/views/add_new_account_view.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/add_new_account_controller.dart'; + +class AddNewAccountView extends GetView { + const AddNewAccountView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + + return Scaffold( + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCreateAccount), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAddAccount), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0), + child: SingleChildScrollView( + child: Column( + children: [ + GetBuilder( + builder: (controller) { + return controller.currencyCodesField = InputField( + refKey: FormFieldConstants.instance().getFormKey("addNewAccountField"), + controller: FormFieldConstants.instance().getController("addNewAccountField"), + labelText: "Select Default Currency", + isDropDown: true, + hintText: "Select Default Currency", + dropDownType: DropDownType.SPECIAL, + items: controller.currencyListDropDown, + onItemSelected: (item) { + controller.updateCurrency(item); + }, + ); + }, + ), + controller.nameAddressField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + hintText: "Enter account title", + labelText: "Account Title", + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.addressFieldLength)], + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + // const SizedBox(height: 30), + // Padding( + // padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + // child: CustomButton( + // onPressed: () { + // controller.validateAndSendRequest(); + // }, + // buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCreateAccount), + // buttonColor: AppColors.colorButton, + // buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + // ), + // ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/agent_location/bindings/agent_location_binding.dart b/lib/app/modules/agent_location/bindings/agent_location_binding.dart new file mode 100644 index 0000000..2386f2d --- /dev/null +++ b/lib/app/modules/agent_location/bindings/agent_location_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/agent_location_controller.dart'; +// +// class AgentLocationBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => AgentLocationController(), +// ); +// } +// } diff --git a/lib/app/modules/agent_location/controllers/agent_location_controller.dart b/lib/app/modules/agent_location/controllers/agent_location_controller.dart new file mode 100644 index 0000000..a3b0e3e --- /dev/null +++ b/lib/app/modules/agent_location/controllers/agent_location_controller.dart @@ -0,0 +1,142 @@ +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/services.dart'; +// import 'package:flutter_svg/flutter_svg.dart'; +// import 'package:get/get.dart'; +// // import 'package:google_maps_flutter/google_maps_flutter.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/app_assets.dart'; +// import 'package:uco_mobile_poc_project/app/models/Branch.dart'; +// +// class AgentLocationController extends GetxController { +// final TextEditingController searchController = TextEditingController(); +// +// // BuildContext context = Get.context as BuildContext; +// // final RxSet markers = {}.obs; +// // final List mapType = ['Normal', 'Satellite', 'Hybrid'].obs; +// // BitmapDescriptor? myMarker; +// // Rx selectedMapType = MapType.normal.obs; +// // +// // /// Change Map Type +// // void changeMapType(MapType newMapType) { +// // selectedMapType.value = newMapType; +// // } +// // +// // @override +// // void onInit() { +// // super.onInit(); +// // +// // /// Initialize with some default markers +// // searchBranches('Normal'); +// // } +// // +// // void searchBranches(String branchName) { +// // /// Simulate fetching branch locations based on the city +// // /// Replace this with your actual logic to get branch locations +// // List branches = getBranches(branchName); +// // +// // /// Clear existing markers +// // markers.clear(); +// // +// // /// Add markers for each branch in the selected city +// // if (branches.isNotEmpty) { +// // branches.forEach((branch) async { +// // markers.add( +// // Marker( +// // markerId: MarkerId(branch.name), +// // position: LatLng(branch.latitude, branch.longitude), +// // icon: await BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen), +// // +// // onTap: () { +// // showCustomInfoWindow(branch); +// // }, +// // // infoWindow: InfoWindow( +// // // title: branch.name, +// // // snippet: branch.contactNumber, +// // // ), +// // ), +// // ); +// // }); +// // update(); +// // } +// // } +// +// /// Custom Info Window for marker +// void showCustomInfoWindow(Branch branch) { +// Clipboard.setData(ClipboardData(text: branch.name)); +// Clipboard.setData(ClipboardData(text: branch.contactNumber)); +// Clipboard.setData(ClipboardData(text: branch.address)); +// Get.defaultDialog( +// contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), +// title: branch.name, +// titlePadding: const EdgeInsets.only(top: 10), +// titleStyle: Theme.of(context).textTheme.titleSmall!.copyWith(fontWeight: FontWeight.w500), +// content: Column( +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// Row( +// crossAxisAlignment: CrossAxisAlignment.center, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Image.asset( +// AppAssets.lg_mfsys, // Replace with your logo image path +// width: 35, +// height: 35, +// ), +// const SizedBox(width: 10), +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Row( +// children: [ +// const Icon( +// Icons.location_on, +// size: 13, +// color: Colors.blue, +// ), +// const SizedBox( +// height: 20, +// ), +// Padding( +// padding: const EdgeInsets.only(left: 10.0), +// child: Text('MFSYS Technologies', style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w400)), +// ), +// ], +// ), +// const SizedBox(height: 10), +// Row( +// children: [ +// const Icon( +// Icons.phone, // Replace with your desired icon +// size: 13, +// color: Colors.blue, +// ), +// const SizedBox(height: 8), +// Padding( +// padding: const EdgeInsets.only(left: 10.0), +// child: Text( +// style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w400), +// '(051) 41021712', +// ), +// ), +// ], +// ), +// ], +// ), +// ], +// ), +// ], +// ), +// ); +// } +// +// /// Branches List +// List getBranches(String cityName) { +// return [ +// Branch(name: 'MFSYS Technolog', latitude: 37.7749, longitude: -122.4194, contactNumber: '123-456-7890', address: "Main Branch I9/3"), +// Branch(name: 'MFSYS Technolog', latitude: 37.7831, longitude: -122.4039, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// Branch(name: 'MFSYS Technolog', latitude: 37.7841, longitude: -122.4539, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// Branch(name: 'Branch E', latitude: 37.7867, longitude: -122.4089, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// ]; +// } +// } diff --git a/lib/app/modules/agent_location/views/agent_location_view.dart b/lib/app/modules/agent_location/views/agent_location_view.dart new file mode 100644 index 0000000..f8affdc --- /dev/null +++ b/lib/app/modules/agent_location/views/agent_location_view.dart @@ -0,0 +1,95 @@ +// import 'package:flutter/material.dart'; +// import 'package:get/get.dart'; +// import 'package:google_maps_flutter/google_maps_flutter.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_app_bar.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_colors.dart'; +// +// import '../controllers/agent_location_controller.dart'; +// +// class AgentLocationView extends GetView { +// const AgentLocationView({Key? key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: DashBoardAppBar( +// title: TranslationKeys.makeTranslation(TranslationKeys.textMapLocationTitle), +// onBackButtonPressed: () { +// Get.back(); +// }, +// actions: [ +// PopupMenuButton( +// color: AppColors.white, +// icon: const Icon( +// Icons.more_vert, +// color: AppColors.white, // Set your desired color for the actions dots +// ), +// onSelected: (selectedMapType) { +// controller.changeMapType(selectedMapType); +// }, +// itemBuilder: (BuildContext context) { +// return [ +// PopupMenuItem( +// value: MapType.normal, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textNormalMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// PopupMenuItem( +// value: MapType.satellite, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textSatelliteMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// PopupMenuItem( +// value: MapType.hybrid, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textHybridMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// ]; +// }, +// ), +// ], +// ), +// body: Obx(() { +// return GoogleMap( +// mapType: controller.selectedMapType.value, +// initialCameraPosition: const CameraPosition( +// target: LatLng(37.7749, -122.4194), +// zoom: 12.0, +// ), +// markers: controller.markers.toSet(), +// onMapCreated: (GoogleMapController controller) { +// /// You can use the controller for further map customization +// }, +// onTap: (LatLng latLng) { +// /// Close any existing dialogs when tapping on the map +// // Get.back(); +// +// /// Find the tapped marker based on its position +// final tappedMarker = controller.markers.firstWhere( +// (marker) => marker.position == latLng, +// ); +// +// final tappedBranch = controller.getBranches(controller.mapType.first)[0]; +// Get.defaultDialog( +// title: tappedBranch.name, +// content: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text('${TranslationKeys.makeTranslation(TranslationKeys.textMapContactNumber)} ${tappedBranch.contactNumber}'), +// Text('${TranslationKeys.makeTranslation(TranslationKeys.textMapContactNumber)} ${tappedBranch.contactNumber}'), +// ], +// ), +// ); +// }, +// ); +// }), +// ); +// } +// } diff --git a/lib/app/modules/app_intro/bindings/intro_screen_binding.dart b/lib/app/modules/app_intro/bindings/intro_screen_binding.dart new file mode 100644 index 0000000..d16f567 --- /dev/null +++ b/lib/app/modules/app_intro/bindings/intro_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/intro_screen_controller.dart'; + +class IntroScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => IntroScreenController(), + ); + } +} diff --git a/lib/app/modules/app_intro/controllers/intro_screen_controller.dart b/lib/app/modules/app_intro/controllers/intro_screen_controller.dart new file mode 100644 index 0000000..0bc7ce6 --- /dev/null +++ b/lib/app/modules/app_intro/controllers/intro_screen_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class IntroScreenController extends GetxController { + //TODO: Implement IntroScreenController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/app_intro/views/intro_screen_view.dart b/lib/app/modules/app_intro/views/intro_screen_view.dart new file mode 100644 index 0000000..3ab3059 --- /dev/null +++ b/lib/app/modules/app_intro/views/intro_screen_view.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:introduction_slider/source/presentation/pages/introduction_slider.dart'; +import 'package:introduction_slider/source/presentation/widgets/buttons.dart'; +import 'package:introduction_slider/source/presentation/widgets/dot_indicator.dart'; +import 'package:introduction_slider/source/presentation/widgets/introduction_slider_item.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/intro_screen_controller.dart'; + +class IntroScreenView extends GetView { + IntroScreenView({Key? key}) : super(key: key); + double imageWidthHeight = 180; + + @override + Widget build(BuildContext context) { + // + // dp("Width int screen", {MediaQuery.sizeOf(Get.context!).width}); + // dp("Height init screen ", MediaQuery.sizeOf(Get.context!).height); + + // dp("Display large ", Theme.of(Get.context!).textTheme.displayLarge); + + return Scaffold( + backgroundColor: AppColors.colorSecondary, + body: IntroductionSlider( + showStatusBar: true, + items: [ + IntroductionSliderItem( + logo: SvgPicture.asset( + AppAssets.img_global, + width: imageWidthHeight, + height: imageWidthHeight, + ), + title: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textWelcomeToJoin), + style: Theme.of(context).textTheme.displayLarge!, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textIntroDescription), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(height: 1.8), + textAlign: TextAlign.center, + ), + ], + ), + ), + backgroundColor: AppColors.colorSecondary, + ), + IntroductionSliderItem( + logo: SvgPicture.asset( + AppAssets.img_slider, + width: imageWidthHeight, + height: imageWidthHeight, + ), + title: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textWelcomeToJoin), style: Theme.of(context).textTheme.displayLarge), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textIntroDescription), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(height: 1.8), + textAlign: TextAlign.center, + ), + ], + ), + ), + backgroundColor: AppColors.colorSecondary, + ), + ], + done: Done( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: CustomButton( + onPressed: () { + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + buttonColor: AppColors.colorPrimaryLight, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.continueText), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimaryDark), + buttonPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 35), + ), + ), + home: Container(), + ), + dotIndicator: const DotIndicator(size: 10, selectedColor: AppColors.colorPrimary), + // back: Back( + // child: Padding( + // padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + // child: CustomButton( + // onPressed: () { + // // Get.offAndToNamed(Routes.SIGN_UP_SCREEN_STEP1); + + // Get.back(); + // }, + // buttonColor: AppColors.colorPrimaryLight, + // buttonText: + // TranslationKeys.makeTranslation(TranslationKeys.textRegister), + // textStyle: Theme.of(context) + // .textTheme + // .titleSmall + // ?.copyWith(color: AppColors.colorPrimaryDark), + // buttonPadding: + // const EdgeInsets.symmetric(vertical: 7, horizontal: 25), + // ), + // ), + // ), + ), + ); + } +} diff --git a/lib/app/modules/app_setting/bindings/app_setting_binding.dart b/lib/app/modules/app_setting/bindings/app_setting_binding.dart new file mode 100644 index 0000000..aa8951e --- /dev/null +++ b/lib/app/modules/app_setting/bindings/app_setting_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/app_setting_controller.dart'; + +class AppSettingBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AppSettingController(), + ); + } +} diff --git a/lib/app/modules/app_setting/controllers/app_setting_controller.dart b/lib/app/modules/app_setting/controllers/app_setting_controller.dart new file mode 100644 index 0000000..efcb37d --- /dev/null +++ b/lib/app/modules/app_setting/controllers/app_setting_controller.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_contants.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../routes/app_pages.dart'; + + +class AppSettingController extends GetxController { + static bool isDarkMode = false; + static RxBool isRTL = false.obs; + static RxString selectedLocale = "en".obs; + + // LocaleController localeController = LocaleController(); + + + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + AppSettingController.isRTL.value = Get.locale!.languageCode == "ar" || Get.locale!.languageCode == "ur"; + AppSettingController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, AppSettingController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, AppSettingController.isRTL.value); + Get.forceAppUpdate(); + update(); + } + + @override + void onInit() { + super.onInit(); + } + + void changeAppMode(bool value) async { + AppStorage.putBoolean(AppConstants.IS_DARK_MODE, value); + isDarkMode = value; + } + + void showLogoutDialog(BuildContext context) { + CustomDialog.showLogoutDialog( + context: context, + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + ); + } +} + +class AppSettings { + String title; + String description; + Icon icon; + Function() onTap; + + AppSettings({required this.title, required this.description, required this.icon, required this.onTap}); +} diff --git a/lib/app/modules/app_setting/views/app_setting_view.dart b/lib/app/modules/app_setting/views/app_setting_view.dart new file mode 100644 index 0000000..ebf2d3d --- /dev/null +++ b/lib/app/modules/app_setting/views/app_setting_view.dart @@ -0,0 +1,466 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/bottom_sheet.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/app_setting_controller.dart'; +import 'model/Language.dart'; + +class AppSettingView extends GetView { + const AppSettingView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAppSettingTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + showBottomSheet(context, "FROM_ACCOUNT", controller); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon(Icons.language, color: AppColors.colorPrimary, size: 18), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLanguagesTitle), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey700), + ), + ], + ), + ), + ), + ), + ), + Visibility( + // visible: SessionCache.instance.fingerPrintController.isFingerprintSupported.value, + child: Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + // showBottomSheet( + // context, "FROM_ACCOUNT", controller); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.fingerprint_outlined, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textFingerPrintTitle), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + // Obx(() { + // return Switch( + // value: SessionCache.instance.fingerPrintController.isFingerprintSupported.value && SessionCache.instance.fingerPrintController.isFingerPrintExistInDB.value, + // onChanged: (bool value) { + // if (value) { + // SessionCache.instance.fingerPrintController.authenticate(null, true); + // } else { + // print("---------------->>>"); + // SessionCache.instance.fingerPrintController.clearFromDB(); + // } + // }, + // activeColor: AppColors.colorButton, + // ); + // }), + ], + ), + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.DAIL_TRANSACTION_LIMIT); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.monetization_on_outlined, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDailyTransactionLimit), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.QR_SETTING); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.qr_code, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textQRSetting), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.CHANGE_TRANSACTION_PIN); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.password, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textChangeTransactionPin), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Toasty.success("Transaction Pin Already Generate"); + // Get.toNamed(Routes.CREATE_TRANSACTION_PIN); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.password, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCreateTransactionPin), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + controller.showLogoutDialog(context); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.logout, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + const Expanded(flex: 0, child: SizedBox(height: 15)), + ], + ), + ), + ); + } + + /// Change Language Function For Search Bar + void showBottomSheet(BuildContext context, String accountType, AppSettingController controller) { + // + + List options = []; + + for (int i = 0; i < Languages.supportedLanguages.length; i++) { + // + + Languages language = Languages.supportedLanguages[i]; + + options.add(OptionData.withData(language.lable, "", language)); + + // + } + + Get.bottomSheet( + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorGrey800, width: 1), borderRadius: const BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, (selectedOption) { + Languages language = selectedOption.dataObject as Languages; + print("===========$language"); + controller.updateLanguage(language.locale); + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +class DialogDesign extends StatelessWidget { + List options = []; + Function(OptionData) onSelect; + + DialogDesign(this.options, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textSelectYourOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith(color: AppColors.titleColor, fontSize: 12, fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); // Close the bottom sheet using Get + }, + child: const CircleAvatar( + radius: 12.5, + backgroundColor: Colors.transparent, + child: Icon( + Icons.close, + size: 16.0, + color: Colors.red, + ), + ), + ), + ], + ), + const SizedBox(height: 10.0), + FilterableBottomSheet(options: options, onSelect: onSelect), + ], + ), + ); + } +} diff --git a/lib/app/modules/app_setting/views/model/Language.dart b/lib/app/modules/app_setting/views/model/Language.dart new file mode 100644 index 0000000..5515381 --- /dev/null +++ b/lib/app/modules/app_setting/views/model/Language.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import '../../../../core/constants/translation_keys.dart'; + +class Languages { + String lable = ""; + Locale locale; + String code; + + Languages({required this.lable, required this.locale, required this.code}); + + static List supportedLanguages = [ + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageEnglish), locale: const Locale('en', 'US'), code: "en"), + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageArabic), locale: const Locale('ar', 'SA'), code: "ar"), + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageUrdu), locale: const Locale('ur', 'PK'), code: "ur"), + ]; +} diff --git a/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart b/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart new file mode 100644 index 0000000..46d4c0c --- /dev/null +++ b/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/beneficiary_management_controller.dart'; + + +class BeneficiaryManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryManagementController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart b/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart new file mode 100644 index 0000000..7e3d1c5 --- /dev/null +++ b/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart @@ -0,0 +1,76 @@ +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; + + +class BeneficiaryManagementController extends GetxController { + final AppRepositories repository = Get.find(); + String className = ""; + var hasUpdated = false.obs; + + List allBeneficiary = []; + RxList filteredBeneficiaries = [].obs; + + /// Fetch All Beneficiary Function + Future fetchAllBeneficiary(String porOrgacode, String email) async { + try { + ServerResponse response = await repository.fetchAllBeneficiary(porOrgacode, email); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + // Assuming the response contains a list of beneficiary account data + List data = response.response; + if (data != null) { + List beneficiaryList = data.map((item) { + return BeneficiaryAccountModel.fromMap(item); + }).toList(); + + // Update the RxList with the fetched data + allBeneficiary.assignAll(beneficiaryList); + filteredBeneficiaries.assignAll(beneficiaryList); + } + } catch (e) { + Toasty.error('An error occurred while fetching beneficiary accounts.'); + } + } + + /// Delete Beneficiary Function + Future deleteSingleBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) async { + ServerResponse response = await repository.deleteBeneficiary(mbmBkmsnumberRef, email, porOrgacode); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success('Your Beneficiary account Delete successfully.'); + fetchBeneficiaries(); + } + + @override + void onInit() { + super.onInit(); + fetchBeneficiaries(); + } + + void fetchBeneficiaries() async { + await fetchAllBeneficiary(SessionCache.instance.userInfo.porOrgacode, SessionCache.instance.userInfo.cmpUserId); + dp("All Beneficiary List======== ", allBeneficiary.toString()); + } + + void filterBeneficiaries(String searchText) { + if (searchText.isEmpty) { + filteredBeneficiaries.assignAll(allBeneficiary); + } else { + filteredBeneficiaries.assignAll(allBeneficiary.where((beneficiary) { + return beneficiary.refNickName.toLowerCase().contains(searchText.toLowerCase()) || beneficiary.mbmBkmstitleRef.toLowerCase().contains(searchText.toLowerCase()) || beneficiary.mbmBkmsnumberRef.toLowerCase().contains(searchText.toLowerCase()); + }).toList()); + } + } + +} diff --git a/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart b/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart new file mode 100644 index 0000000..d4ffd50 --- /dev/null +++ b/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/beneficiary_management_controller.dart'; + +class BeneficiaryManagementView extends GetView { + const BeneficiaryManagementView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Beneficiary Management", + onBackButtonPressed: () { + Get.back(result: controller.hasUpdated.value); + }, + ) + : null, + floatingActionButton: InkWell( + onTap: () async { + var result = await Get.toNamed(Routes.NEW_BENEFICIARY); + if (result != null && result == true) { + controller.fetchBeneficiaries(); + controller.hasUpdated.value = true; + } + }, + child: Container( + height: 30, + width: 130, + decoration: const BoxDecoration(color: AppColors.colorButton, borderRadius: BorderRadius.all(Radius.circular(20.0))), + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Icon(Icons.add, size: 14, color: AppColors.white), SizedBox(width: 5), Text("Add Beneficiary", style: TextStyle(color: AppColors.white, fontWeight: FontWeight.w500, fontSize: 12))], + ), + ), + ), + body: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + suffixIconColor: AppColors.colorPrimary, + filled: true, + fillColor: AppColors.colorGrey200, + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: Colors.transparent)), + border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: AppColors.colorGrey500)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, style: BorderStyle.solid, color: Colors.transparent)), + hintText: 'Search By Beneficiary Name', + hintStyle: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorGrey500), + suffixIcon: Icon(Icons.search_rounded), + ), + onChanged: (value) { + controller.filterBeneficiaries(value); + }), + ), + Container( + height: 40, + width: double.infinity, + color: AppColors.FDF7F1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 10.0), + child: Text("Bank Transfer", style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13)), + ), + ), + const SizedBox(height: 20.0), + Obx(() { + if (controller.filteredBeneficiaries.isEmpty) { + return const Center( + child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), + ); + } else { + return ListView.separated( + shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final beneficiary = controller.filteredBeneficiaries[index]; + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.all(15.0), + decoration: const BoxDecoration( + color: AppColors.white, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Row( + children: [ + CircleAvatar(radius: 20.0, backgroundColor: AppColors.colorGrey300, child: Text(AppUtils.getInitials(beneficiary.mbmBkmstitleRef), style: Theme.of(context).textTheme.titleSmall)), + const SizedBox(width: 10), + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(beneficiary.refNickName, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey700, fontWeight: FontWeight.w500, fontSize: 14)), + const SizedBox(height: 5), + Text(beneficiary.mbmBkmstitleRef, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey600, fontWeight: FontWeight.w400, fontSize: 12)), + const SizedBox(height: 5), + Text(beneficiary.mbmBkmsnumberRef, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorPrimary, fontWeight: FontWeight.w400, fontSize: 12)), + ], + ), + ), + Expanded( + flex: 1, + child: Align( + alignment: Alignment.centerRight, + child: PopupMenuButton( + padding: const EdgeInsets.all(0.0), + offset: const Offset(-25, 30), + color: AppColors.white, + icon: const Icon(Icons.more_vert_rounded, color: AppColors.colorGrey500), + onSelected: (value) {}, + itemBuilder: (context) => [ + _buildPopupMenuItem(context, "Pay", 0, () { + Get.toNamed(Routes.BENEFICIARY_TRANSFER_MONEY, arguments: [beneficiary]); + }), + _buildPopupMenuItem(context, "Delete", 1, () { + CustomDialog.showAlertDialog( + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + controller.deleteSingleBeneficiary(beneficiary.mbmBkmsnumberRef, SessionCache.instance.userInfo.cmpUserId, SessionCache.instance.userInfo.porOrgacode); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + context: context); + }), + ], + ), + ), + ), + ], + ), + ), + ], + ); + }, + separatorBuilder: (BuildContext context, int index) { + return Container(height: 1, color: AppColors.black.withOpacity(0.2)); + }, + itemCount: controller.filteredBeneficiaries.length, + ); + } + }), + ], + ), + ), + ); + } + + /// For List Actions + PopupMenuItem _buildPopupMenuItem(BuildContext context, String text, int value, Function() onTap) { + return PopupMenuItem( + height: 10, + onTap: onTap, + value: value, + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0), + child: Text(text, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500)), + ), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart b/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart new file mode 100644 index 0000000..25ad44d --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/beneficiary_transfer_controller.dart'; + + +class BeneficiaryTransferBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryTransferController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart b/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart new file mode 100644 index 0000000..012d90e --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../models/SendTransactionStep1ResponseModel.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + +class BeneficiaryTransferController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + RxBool isResend = false.obs; + + //drop down + RxList allFromAccounts = RxList.empty(); + Rx selectedFromAccount = DepositAccount.empty().obs; + + RxList allToAccounts = RxList.empty(); + Rx selectedToAccount = DepositAccount.empty().obs; + ExchangeRate? selectedExchangeRate; + + TextEditingController referenceCodeController = TextEditingController(); + + // fields + late InputField fromAccountField; + late InputField toAccountField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + late String beneficiaryName; + List beneficiaryDetail = []; + + @override + void onInit() { + super.onInit(); + beneficiaryDetail = Get.arguments ?? []; + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + allFromAccounts.add(DropDown(depositAccount.mbmBkmsnumber, "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + } + } + + @override + Future onReady() async { + super.onReady(); + disposeAllResources(); + onFromAccountSelection(allFromAccounts.elementAt(0)); + fromAccountField.setText((allFromAccounts.first.label)); + + /// For Set To Account Based on selected + if (beneficiaryDetail.isNotEmpty) { + toAccountField.setText(beneficiaryDetail.first.mbmBkmstitleRef); + } + + /// For Getting Exchange Rate + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == beneficiaryDetail.first.pcrCurrcode) { + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void onFromAccountSelection(DropDown value) { + if (value.id == selectedToAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + fromAccountField.setText(""); + selectedFromAccount.value = DepositAccount.empty(); + } else { + selectedFromAccount.value = value.data as DepositAccount; + } + } + + void disposeAllResources() { + fromAccountField.clear(); + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + fromAccountField, + toAccountField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + /// Send Transaction function + Future sendBeneficiaryTransaction({navigate = true}) async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + drMbmBkmsnumber: selectedFromAccount.value.mbmBkmsnumber, + drMbmBkmstitle: selectedFromAccount.value.mbmBkmstitle, + drPcrCurrcode: selectedFromAccount.value.pcrCurrcode, + drPcrCurrdesc: selectedFromAccount.value.pcrCurrdesc, + drPcrCurrshort: selectedFromAccount.value.pcrCurrshort, + crMbmBkmsnumber: beneficiaryDetail.first.mbmBkmsnumberRef, + crMbmBkmstitle: beneficiaryDetail.first.mbmBkmstitleRef, + crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + sgtGntrnarration: "", + dmpProdCode: selectedFromAccount.value.dmpProdcode, + transType: "DR", + notificationId: "", + transMode: "Online", + sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + otdTrancomment: messageField.getCustomText(), + isOtpRequired: false, + cmpRefcode: referenceCodeField.getCustomText(), + ); + + TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + pinType: "TRAN", + transPincode: userTransactionPinField.getCustomText(), + isOtpRequired: false, + ); + + ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + + if (navigate) { + Get.toNamed(Routes.BENEFICIARY_TRANSFER_MONEY_OTP, arguments: { + AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + AppConstants.SEND_TRANS_PIN_REQUEST: transactionPinRequestModel, + AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + }); + } else { + Fluttertoast.showToast( + msg: "OTP successfully send to your email address", + ); + } + } + + void clearTransaction() { + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart b/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart new file mode 100644 index 0000000..3c669f5 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart @@ -0,0 +1,394 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/beneficiary_transfer_controller.dart'; + +class BeneficiaryTransferView extends GetView { + const BeneficiaryTransferView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Beneficiary Payment", + /*TranslationKeys.makeTranslation(TranslationKeys.textUSend),*/ + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.fromAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}fromAccountField"), + controller: FormFieldConstants.instance().getController("${className}fromAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allFromAccounts, + onItemSelected: (item) { + // controller.updateSelectedDeposit(item!); + controller.onFromAccountSelection(item!); + }, + ), + controller.toAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}toAccountField"), + controller: FormFieldConstants.instance().getController("${className}toAccountField"), + labelText: "To Account", + readOnly: true, + showCursor: false, + ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendBeneficiaryTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendBeneficiaryTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + // const SizedBox(width: 10), + // Expanded( + // flex: 1, + // child: CustomButton( + // onPressed: () { + // FocusScope.of(context).requestFocus(FocusNode()); + // controller.clearTransaction(); + // controller.disposeAllResources(); + // }, + // buttonPadding: const EdgeInsets.symmetric(vertical: 11), + // buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + // buttonColor: AppColors.colorSkipBtn, + // textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + // sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + // ), + // ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, BeneficiaryTransferController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, BeneficiaryTransferController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart b/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart new file mode 100644 index 0000000..e2b7a35 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/beneficiary_transfer_otp_controller.dart'; + + +class BeneficiaryTransferOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryTransferOtpController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart b/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart new file mode 100644 index 0000000..cf2df59 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + + +class BeneficiaryTransferOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + TransactionPinRequestModel pinRequestModel = TransactionPinRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + late DepositAccount fromAccount; + late DepositAccount toAccount; + late List beneficiaryList; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + pinRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_PIN_REQUEST] ?? TransactionPinRequestModel.empty() : TransactionPinRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + transactionSubmitRequestModel.pinType = "TRAN"; + + transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, arguments: { + AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + AppConstants.EXCHANGE_RATE: exchangeRate, + }); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.sendTransactionStep1(pinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart b/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart new file mode 100644 index 0000000..6a55c51 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/beneficiary_transfer_otp_controller.dart'; + + + +class BeneficiaryTransferOtpView extends GetView { + const BeneficiaryTransferOtpView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/bill_management/bindings/bill_management_binding.dart b/lib/app/modules/bill_management/bindings/bill_management_binding.dart new file mode 100644 index 0000000..3c39272 --- /dev/null +++ b/lib/app/modules/bill_management/bindings/bill_management_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/bill_management_controller.dart'; + +class BillManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BillManagementController(), + ); + } +} diff --git a/lib/app/modules/bill_management/controllers/bill_management_controller.dart b/lib/app/modules/bill_management/controllers/bill_management_controller.dart new file mode 100644 index 0000000..1e87838 --- /dev/null +++ b/lib/app/modules/bill_management/controllers/bill_management_controller.dart @@ -0,0 +1,6 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/bill_management/views/bill_management_view.dart'; + +class BillManagementController extends GetxController { + +} diff --git a/lib/app/modules/bill_management/views/bill_management_view.dart b/lib/app/modules/bill_management/views/bill_management_view.dart new file mode 100644 index 0000000..25e009d --- /dev/null +++ b/lib/app/modules/bill_management/views/bill_management_view.dart @@ -0,0 +1,149 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/bill_management_controller.dart'; + +class BillManagementView extends GetView { + const BillManagementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBill), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectBillType), style: Theme.of(context).textTheme.titleSmall!.copyWith(color: AppColors.colorTitle)), + ), + const SizedBox(height: 20), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + bottomSheetLogin.icon, + width: 50, + ), + const SizedBox(height: 10), + Center( + child: LabelText(fontSize: 12, bottomSheetLogin.description), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ), + ); + } + + static List options = [ + BottomSheetLogin( + billTypes: "${BillType.electricity}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity), + icon: AppAssets.ic_electricity, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.electricity); + }), + BottomSheetLogin( + billTypes: "${BillType.gas}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGas), + icon: AppAssets.ic_gas, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.gas); + }), + BottomSheetLogin( + billTypes: "${BillType.internet}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityInternet), + icon: AppAssets.ic_internet, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.internet); + }), + BottomSheetLogin( + billTypes: "${BillType.water}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityWater), + icon: AppAssets.ic_water, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.water); + }), + // BottomSheetLogin( + // billTypes: "${BillType.creditCard}", + // description: TranslationKeys.makeTranslation( + // TranslationKeys.transUtilityCreditCard), + // icon: AppAssets.ic_card, + // onTap: () { + // Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, + // arguments: BillType.creditCard); + // }), + ]; +} + +/// Enum to represent different bill types +enum BillType { + electricity, + gas, + internet, + ptcl, + water, + creditCard, + utilityAJKBARKIYAT, + utilityFESCO, + utilityGBBARKIYAT, + utilityIESCO, + utilityGEPCO, + utilityHESCO, + pakGasAgency, + suitGas, + fiber, + zong, + nestle, + aqua, + pepsiCo, + minerva, +} diff --git a/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart b/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart new file mode 100644 index 0000000..d35f5df --- /dev/null +++ b/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/bill_management_category_controller.dart'; + +class BillManagementCategoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BillManagementCategoryController(), + ); + } +} diff --git a/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart b/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart new file mode 100644 index 0000000..1d105ce --- /dev/null +++ b/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart @@ -0,0 +1,247 @@ +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../routes/app_pages.dart'; +import '../../bill_management/views/bill_management_view.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; + + +class BillManagementCategoryController extends GetxController { + List getOptions(BillType? selectedBillType) { + switch (selectedBillType) { + case BillType.electricity: + return optionsElectricity; + case BillType.gas: + return optionsGas; + case BillType.internet: + return optionsInternet; + case BillType.water: + return optionsWater; + default: + return []; + } + } + + String getBillTypeCategory(BillType? billType) { + switch (billType) { + case BillType.electricity: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity); + case BillType.gas: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityGas); + case BillType.internet: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityInternet); + case BillType.water: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityWater); + default: + return ''; + } + } + + /// Helper function to get category based on bill type + String getBillTypeCategoryS(BillType? billType) { + switch (billType) { + case BillType.electricity: + return 'Electricity Bill'; + case BillType.gas: + return 'Gas Bill'; + case BillType.internet: + return 'Internet Bill'; + case BillType.water: + return 'Water Bill'; + default: + return 'Unknown'; + } + } + + List optionsElectricity = [ + BottomSheetLogin( + billTypes: "${BillType.utilityAJKBARKIYAT}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityAJKBARKIYAT), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityAJKBARKIYAT}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityAJKBARKIYAT), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityFESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityFESCO), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityFESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityFESCO), + "icon": AppAssets.ic_multan, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityGBBARKIYAT}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGBBARKIYAT), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityGBBARKIYAT}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityGBBARKIYAT), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityIESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGEPCO), + icon: AppAssets.ic_khan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityIESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityGEPCO), + "icon": AppAssets.ic_khan, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityGEPCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityHESCO), + icon: AppAssets.ic_ke, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityGEPCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityHESCO), + "icon": AppAssets.ic_ke, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityHESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityIESCO), + icon: AppAssets.ic_kc, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityHESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityIESCO), + "icon": AppAssets.ic_kc, + }); + }), + ]; + + List optionsGas = [ + BottomSheetLogin( + billTypes: "${BillType.pakGasAgency}", + description: TranslationKeys.makeTranslation(TranslationKeys.transPakGasAgency), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.pakGasAgency}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transPakGasAgency), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.suitGas}", + description: TranslationKeys.makeTranslation("Sui Gas"), + icon: AppAssets.ic_gas, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.suitGas}", + "description": TranslationKeys.makeTranslation("Sui Gas"), + "icon": AppAssets.ic_sui_gas, + }); + }), + ]; + + List optionsInternet = [ + BottomSheetLogin( + billTypes: "${BillType.fiber}", + description: TranslationKeys.makeTranslation(TranslationKeys.transFiber), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.fiber}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transFiber), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.zong}", + description: TranslationKeys.makeTranslation(TranslationKeys.transZong), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.zong}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transZong), + "icon": AppAssets.ic_multan, + }); + }), + ]; + + List optionsWater = [ + BottomSheetLogin( + billTypes: "${BillType.nestle}", + description: TranslationKeys.makeTranslation(TranslationKeys.transNestle), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.nestle}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transNestle), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.aqua}", + description: TranslationKeys.makeTranslation(TranslationKeys.transAquaFujitenma), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.aqua}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transAquaFujitenma), + "icon": AppAssets.ic_multan, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.pepsiCo}", + description: TranslationKeys.makeTranslation(TranslationKeys.transPepsiCo), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.pepsiCo}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transPepsiCo), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.minerva}", + description: TranslationKeys.makeTranslation(TranslationKeys.transMinerva), + icon: AppAssets.ic_khan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.minerva}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transMinerva), + "icon": AppAssets.ic_khan, + }); + }), + ]; +} diff --git a/lib/app/modules/bill_management_category/views/bill_management_category_view.dart b/lib/app/modules/bill_management_category/views/bill_management_category_view.dart new file mode 100644 index 0000000..6a92a33 --- /dev/null +++ b/lib/app/modules/bill_management_category/views/bill_management_category_view.dart @@ -0,0 +1,116 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../bill_management/views/bill_management_view.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/bill_management_category_controller.dart'; + +class BillManagementCategoryView extends GetView { + const BillManagementCategoryView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + BillType? selectedBillType = Get.arguments; + + String category = controller.getBillTypeCategory(selectedBillType); + + List options = controller.getOptions(selectedBillType); + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(category), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSelectCompany), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + ], + ), + ), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only( + left: 15, + right: 15, + top: 0, + bottom: 15, + ), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = controller.getOptions(selectedBillType)[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage(bottomSheetLogin.icon), + width: 50, + ), + const SizedBox(height: 10), + Center( + child: LabelText(fontSize: 12, bottomSheetLogin.description), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/career/bindings/career_binding.dart b/lib/app/modules/career/bindings/career_binding.dart new file mode 100644 index 0000000..5e3435b --- /dev/null +++ b/lib/app/modules/career/bindings/career_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/career_controller.dart'; + +class CareerBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CareerController(), + ); + } +} diff --git a/lib/app/modules/career/controllers/career_controller.dart b/lib/app/modules/career/controllers/career_controller.dart new file mode 100644 index 0000000..5ddb2d0 --- /dev/null +++ b/lib/app/modules/career/controllers/career_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class CareerController extends GetxController { + //TODO: Implement CareerController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/career/views/career_view.dart b/lib/app/modules/career/views/career_view.dart new file mode 100644 index 0000000..24e0603 --- /dev/null +++ b/lib/app/modules/career/views/career_view.dart @@ -0,0 +1,110 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/career_controller.dart'; + +class CareerView extends GetView { + const CareerView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textCareer), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenVerticalPadding), + child: Column( + children: [ + Expanded( + child: ListView.builder( + itemCount: 1, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 3), + child: Card( + elevation: 3, + color: AppColors.colorGrey100, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Container( + decoration: BoxDecoration(color: AppColors.colorText.withOpacity(0.03), borderRadius: const BorderRadius.all(Radius.circular(50))), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + Image.asset(AppAssets.lg_mfsys, height: 25, width: 25), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textJobTitle), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textOfficeAddress), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textJobSkills), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + InkWell( + onTap: (){ + // launch("mailto:info@mfsys.com.pk"); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 3), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorPrimary), + borderRadius: const BorderRadius.all(Radius.circular(5)), + ), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textApply), style: Theme.of(context).textTheme.bodySmall)), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + )), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart b/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart new file mode 100644 index 0000000..efcffea --- /dev/null +++ b/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/change_transaction_pin_controller.dart'; + +class ChangeTransactionPinBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangeTransactionPinController(), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart b/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart new file mode 100644 index 0000000..618350a --- /dev/null +++ b/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../routes/app_pages.dart'; + + +class ChangeTransactionPinController extends GetxController { + TextEditingController oldTransactionPinController = TextEditingController(); + TextEditingController newTransactionPinController = TextEditingController(); + TextEditingController confirmTransactionPinController = TextEditingController(); + + final AppRepositories repository = Get.find(); + + void validateAndSendRequest() async { + if (oldTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + if (newTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + if (confirmTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + // if (oldTransactionPinController.text != newTransactionPinController.text) { + // Toasty.error("Old and New Transaction Pin not match!"); + // return; + // } + + if (newTransactionPinController.text != confirmTransactionPinController.text) { + Toasty.error("New and Confirm Transaction Pin not match!"); + return; + } + + + // ChangeTransactionPinRequest request = ChangeTransactionPinRequest( + // oldTransPincode: oldTransactionPinController.text, + // newTransPincode: newTransactionPinController.text, + // channelCode: RequestConstants.channelCode, + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // isOtpRequired: false, + // pinType: AppConstants.PIN_TYPE_Transaction, + // + // ); + // + // ServerResponse response = await repository.changeTransactionPin(request); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + Get.toNamed(Routes.CHANGE_TRANSACTION_PIN_OTP, + // arguments: { + // 'oldTransactionPin': oldTransactionPinController.text, + // 'newTransactionPin': newTransactionPinController.text, + // 'confirmTransactionPin': confirmTransactionPinController.text, + // AppConstants.CHANGE_TRANSACTION_PIN_OTP: request, + // }, + ); + + clearController(); + } + + void clearController() { + newTransactionPinController.clear(); + confirmTransactionPinController.clear(); + oldTransactionPinController.clear(); + } +} diff --git a/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart b/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart new file mode 100644 index 0000000..b526fb9 --- /dev/null +++ b/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/change_transaction_pin_controller.dart'; + +class ChangeTransactionPinView extends GetView { + const ChangeTransactionPinView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChangeTransactionPin, + ), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOldTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.oldTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + textInputAction: TextInputAction.done, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPleaseCreatenewtransactionpin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.confirmTransactionPinController, + showCursor: true, + textInputAction: TextInputAction.done, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.newTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + textInputAction: TextInputAction.done, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // controller.validateAndSendRequest(); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textNext), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart b/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart new file mode 100644 index 0000000..fba415e --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/change_transaction_pin_otp_controller.dart'; + +class ChangeTransactionPinOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangeTransactionPinOtpController(), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart b/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart new file mode 100644 index 0000000..d2a8140 --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/ChangeTransactionPinRequest.dart'; +import '../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../routes/app_pages.dart'; + +class ChangeTransactionPinOtpController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + late String oldTransactionPin; + late String confirmTransactionPin; + late String newTransactionPin; + ChangeTransactionPinRequest changeTransactionPinOTPRequest = ChangeTransactionPinRequest(); + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + late bool isSomething; + late final request; + + @override + void onReady() { + super.onReady(); + var arguments = Get.arguments; + oldTransactionPin = arguments['oldTransactionPin']; + newTransactionPin = arguments['newTransactionPin']; + confirmTransactionPin = arguments['confirmTransactionPin']; + changeTransactionPinOTPRequest = arguments[AppConstants.CHANGE_TRANSACTION_PIN_OTP]; + + dp("oldTransactionPin>>>>", oldTransactionPin); + dp("newTransactionPin>>>>", newTransactionPin); + dp("confirmTransactionPin>>>>", confirmTransactionPin); + } + + void validateAndSendRequest() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + // + // CreateTransactionPinRequest request = CreateTransactionPinRequest( + // channelCode: RequestConstants.channelCode, + // pctCstycode: RequestConstants.pctCstycode, + // porOrgacode: RequestConstants.porOrgacode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // obpPincode: pinPutController.text, + // pinType: AppConstants.PIN_TYPE_Transaction, + // ); + // + // ServerResponse response = await repository.createTransactionPin(request); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + clearController(); + CustomDialog.showSuccessDialog( + // title: "Congratulations!", + description: "Your Transaction pin successfully ! An send email and message have been sent to you.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.changeTransactionPin(changeTransactionPinOTPRequest); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void clearController() { + pinPutController.clear(); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart b/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart new file mode 100644 index 0000000..284832b --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/change_transaction_pin_otp_controller.dart'; + +class ChangeTransactionPinOtpView extends GetView { + const ChangeTransactionPinOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart b/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart new file mode 100644 index 0000000..dd26199 --- /dev/null +++ b/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_activation_controller.dart'; + +class ChequeActivationBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeActivationController(), + ); + } +} diff --git a/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart b/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart new file mode 100644 index 0000000..1e158f8 --- /dev/null +++ b/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeActivationController extends GetxController { + //TODO: Implement ChequeActivationController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_activation/views/cheque_activation_view.dart b/lib/app/modules/cheque_activation/views/cheque_activation_view.dart new file mode 100644 index 0000000..d1258a0 --- /dev/null +++ b/lib/app/modules/cheque_activation/views/cheque_activation_view.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/cheque_activation_controller.dart'; + +class ChequeActivationView extends GetView { + const ChequeActivationView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeBookActivation), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimary, + onPressed: () { + CustomDialog.showSuccessDialog( + description: "Your cheque is activated, successfully!", + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.back(); + }); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textActivationContent), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Card( + surfaceTintColor: Colors.white, + elevation: 3.0, + child: Container( + decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(10)), border: Border.all(color: AppColors.colorGrey350)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center(child: Text(TranslationKeys.makeTranslation(TranslationKeys.textAccount), style: Theme.of(context).textTheme.titleSmall)), + Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailCustomerName), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textAccountNumber), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textFirstLeaf), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLastLeaf), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart b/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart new file mode 100644 index 0000000..9d69cc9 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_book_request_details_controller.dart'; + +class ChequeBookRequestDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeBookRequestDetailsController(), + ); + } +} diff --git a/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart b/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart new file mode 100644 index 0000000..e5ee2a5 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeBookRequestDetailsController extends GetxController { + //TODO: Implement ChequeBookRequestDetailsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart b/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart new file mode 100644 index 0000000..b3f78d1 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart @@ -0,0 +1,334 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_book_request_details_controller.dart'; + +class ChequeBookRequestDetailsView + extends GetView { + const ChequeBookRequestDetailsView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChequeRequestDetail), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: + const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestContent), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColors.colorGrey350)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeave20), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith( + fontWeight: FontWeight.w600, fontSize: 28)), + InkWell( + onTap: () { + Get.back(); + }, + child: Container( + decoration: BoxDecoration( + color: AppColors.colorButton, + borderRadius: BorderRadius.circular(50), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, vertical: 4), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChange), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.white)), + ), + ), + ), + ], + ), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeaves), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDeliveryAddress), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCharges), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textScheduleCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textDate), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDateContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + ], + ), + ), + ], + ), + ), + ); + } + + /// SuccessFull Dialog...........Transactions + void showTransactionSuccess(BuildContext context) { + Get.dialog( + Dialog( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(2), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + children: [ + Align( + alignment: Alignment.topRight, + child: InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_close, + height: 67, + width: 67, + ), + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textRequestSummary), + style: Theme.of(context) + .textTheme + .titleMedium + ?.copyWith( + fontWeight: FontWeight.w700, fontSize: 24)), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textNumberofLeaves), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeave20), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith( + fontWeight: FontWeight.w600, fontSize: 22)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDeliveryAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textScheduleCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDate), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDateContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, vertical: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textQueryContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, + fontSize: 10, + color: AppColors.colorGrey800)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimaryLight, + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.CHEQUE_MANAGEMENT); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textDeposit), + ), + ), + ], + ), + ], + ), + ), + ), + ), + barrierDismissible: false); + } +} diff --git a/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart b/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart new file mode 100644 index 0000000..edc826a --- /dev/null +++ b/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_deposit_controller.dart'; + +class ChequeDepositBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeDepositController(), + ); + } +} diff --git a/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart b/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart new file mode 100644 index 0000000..9f09bc8 --- /dev/null +++ b/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +class ChequeDepositController extends GetxController { + final List items = [ + '22222222', + '55555555', + '11111111', + '88888888', + ]; + RxString selectedValue = "22222222".obs; + +} diff --git a/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart b/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart new file mode 100644 index 0000000..8eecd71 --- /dev/null +++ b/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart @@ -0,0 +1,307 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_deposit_controller.dart'; + +class ChequeDepositView extends GetView { + const ChequeDepositView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeDeposit), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () { + Get.back(); + // showTransactionSuccess(context); + // controerll.cleanControllers(); + // Get.toNamed(Routes.CHEQUE_MANAGEMENT); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.colorButton, + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + ), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textContinue), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + ), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeStatusContent), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDepositToChequing), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.text1000), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textMax300000), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, color: AppColors.colorText, fontSize: 8)), + ), + ], + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.bodySmall), + Obx(() { + return Container( + width: double.infinity, + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + height: 40, + //padding: EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text( + 'Select Item', + style: TextStyle( + fontSize: 14, + color: Theme.of(context).hintColor, + ), + ), + items: controller.items + .map((String item) => DropdownMenuItem( + value: item, + child: Text( + item, + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorText), + ), + )) + .toList(), + value: controller.selectedValue.value, + onChanged: (String? value) { + controller.selectedValue.value = value!; + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.symmetric(horizontal: 16), + height: 40, + width: 140, + ), + ), + ), + ); + }), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textFrontOfCheque), style: Theme.of(context).textTheme.bodySmall), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBackofCheque), style: Theme.of(context).textTheme.bodySmall), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(top: 5, right: 5), + child: Icon(Icons.close, color: AppColors.colorText, size: 20), + )), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), + child: SvgPicture.asset( + AppAssets.ic_camera, + height: 70, + width: 70, + ), + ), + ], + ), + ), + ], + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(top: 5, right: 5), + child: Icon(Icons.close, color: AppColors.colorText, size: 20), + )), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), + child: SvgPicture.asset(AppAssets.ic_camera, height: 70, width: 70), + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textTryAgain), style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorText, fontWeight: FontWeight.w400, fontSize: 8)), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTryAgain), style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorText, fontWeight: FontWeight.w400, fontSize: 8)), + ], + ), + ], + ), + ), + ); + } + void showTransactionSuccess(BuildContext context) { + Get.dialog( + Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(2), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + children: [ + Align( + alignment: Alignment.topRight, + child: InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_close, + height: 67, + width: 67, + ), + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textRequestSummary), style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700, fontSize: 24)), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textNumberofLeaves), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLeave20), style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w600, fontSize: 22)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDeliveryAddress), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeBookRequestAddress), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textCharges), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textScheduleCharges), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDate), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDateContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textQueryContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 10, color: AppColors.colorGrey800)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimaryLight, + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.CHEQUE_MANAGEMENT); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDeposit), + ), + ), + ], + ), + ], + ), + ), + ), + ), + barrierDismissible: false); + } + +} + diff --git a/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart b/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart new file mode 100644 index 0000000..777c605 --- /dev/null +++ b/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_management_controller.dart'; + +class ChequeManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeManagementController(), + ); + } +} diff --git a/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart b/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart new file mode 100644 index 0000000..4e262f3 --- /dev/null +++ b/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeManagementController extends GetxController { + //TODO: Implement ChequeManagementController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_management/views/cheque_management_view.dart b/lib/app/modules/cheque_management/views/cheque_management_view.dart new file mode 100644 index 0000000..336a4dc --- /dev/null +++ b/lib/app/modules/cheque_management/views/cheque_management_view.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/cheque_management_controller.dart'; + +class ChequeManagementView extends GetView { + const ChequeManagementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeManagement), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + bottomSheetLogin.icon, + width: 50, + ), + const SizedBox(height: 10), + Center( + child: Text(bottomSheetLogin.description, style: Theme.of(context).textTheme.titleSmall), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ), + ); + } + + static List options = [ + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeStatus), + icon: AppAssets.ic_check_status, + onTap: () { + Get.toNamed(Routes.CHEQUE_STATUS); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeDeposit), + icon: AppAssets.ic_cheque_deposit, + onTap: () { + Get.toNamed(Routes.CHEQUE_DEPOSIT); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeActivation), + icon: AppAssets.ic_activation, + onTap: () { + Get.toNamed(Routes.CHEQUE_ACTIVATION); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeRequest), + icon: AppAssets.ic_request, + onTap: () { + Get.toNamed(Routes.CHEQUE_REQUEST); + }), + ]; +} diff --git a/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart b/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart new file mode 100644 index 0000000..f7af196 --- /dev/null +++ b/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_request_controller.dart'; + +class ChequeRequestBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeRequestController(), + ); + } +} diff --git a/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart b/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart new file mode 100644 index 0000000..4a57f8a --- /dev/null +++ b/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeRequestController extends GetxController { + //TODO: Implement ChequeRequestController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_request/views/cheque_request_view.dart b/lib/app/modules/cheque_request/views/cheque_request_view.dart new file mode 100644 index 0000000..282c6df --- /dev/null +++ b/lib/app/modules/cheque_request/views/cheque_request_view.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_request_controller.dart'; + +class ChequeRequestView extends GetView { + const ChequeRequestView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeRequest), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeRequestContent), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ), + const SizedBox(height: 20), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + ChequeRequestModel bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: LabelText(bottomSheetLogin.leave, labelColor: AppColors.colorGrey800, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 5), + Center( + child: LabelText(bottomSheetLogin.description, labelColor: AppColors.colorGrey400, fontSize: 12), + ), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.circular(50), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 4), + child: Text( + bottomSheetLogin.buttonText, + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.black), + ), + ), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ); + } + + static List options = [ + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave20), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave50), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave100), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ]; +} + +class ChequeRequestModel { + String leave; + String description; + String buttonText; + Function()? onTap; + + ChequeRequestModel({required this.leave, required this.description, required this.buttonText, required this.onTap}); +} diff --git a/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart b/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart new file mode 100644 index 0000000..ea91147 --- /dev/null +++ b/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_status_controller.dart'; + +class ChequeStatusBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeStatusController(), + ); + } +} diff --git a/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart b/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart new file mode 100644 index 0000000..59a7070 --- /dev/null +++ b/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeStatusController extends GetxController { + //TODO: Implement ChequeStatusController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_status/views/cheque_status_view.dart b/lib/app/modules/cheque_status/views/cheque_status_view.dart new file mode 100644 index 0000000..10a2f6a --- /dev/null +++ b/lib/app/modules/cheque_status/views/cheque_status_view.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_status_controller.dart'; + +class ChequeStatusView extends GetView { + const ChequeStatusView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeStatus), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed(Routes.CHEQUE_STATUS_HISTORY); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + // ElevatedButton( + // onPressed: () { + // Get.toNamed(Routes.CHEQUE_STATUS_HISTORY); + // }, + // child: Text("Next", style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.btnColor, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // ), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeStatusContent), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeNumber), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart b/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart new file mode 100644 index 0000000..ec3e074 --- /dev/null +++ b/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_status_history_controller.dart'; + +class ChequeStatusHistoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeStatusHistoryController(), + ); + } +} diff --git a/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart b/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart new file mode 100644 index 0000000..4f3f7e8 --- /dev/null +++ b/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeStatusHistoryController extends GetxController { + //TODO: Implement ChequeStatusHistoryController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart b/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart new file mode 100644 index 0000000..46bb17e --- /dev/null +++ b/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart @@ -0,0 +1,183 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/cheque_status_history_controller.dart'; + +class ChequeStatusHistoryView extends GetView { + const ChequeStatusHistoryView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChequeStatusHistory), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeStatusHistoryContent), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 20), + Card( + surfaceTintColor: Colors.white, + elevation: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + left: BorderSide( + color: AppColors.colorPrimary, + width: 5.0, + ), + ), + ), + child: Card( + surfaceTintColor: Colors.white, + elevation: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context).textTheme.titleSmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusCheckNumber), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusHistoryRefNo), + style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, horizontal: 8.0), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.check, + color: AppColors.colorPrimary, size: 16), + SizedBox(width: 5), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textChequeStatusHistorySuccess), + style: + Theme.of(context).textTheme.bodySmall), + ], + ), + ) + ], + ), + ], + ), + ), + ), + ), + SizedBox(height: 10), + Card( + surfaceTintColor: Colors.white, + elevation: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + left: BorderSide( + color: AppColors.colorPrimary, + width: 5.0, // specify the width of the border + ), + ), + ), + child: Card( + surfaceTintColor: Colors.white, + elevation: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context).textTheme.titleSmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusCheckNumber), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusHistoryRefNo), + style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, horizontal: 8.0), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.close, + color: AppColors.colorPrimary, size: 16), + SizedBox(width: 5), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textChequeStatusHistoryCancel), + style: + Theme.of(context).textTheme.bodySmall), + ], + ), + ) + ], + ), + ], + ), + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart b/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart new file mode 100644 index 0000000..fc4607e --- /dev/null +++ b/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/contacts_screen_controller.dart'; +// +// class ContactsScreenBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => ContactsScreenController(), +// ); +// } +// } diff --git a/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart b/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart new file mode 100644 index 0000000..3355367 --- /dev/null +++ b/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart @@ -0,0 +1,105 @@ +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter_contacts/flutter_contacts.dart'; +// import 'package:get/get.dart'; +// import 'package:permission_handler/permission_handler.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/app_contants.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/core/dialogs/custom_loading.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/Fields/input_field.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_toasty.dart'; +// +// class ContactsScreenController extends GetxController { +// static TextEditingController phoneController = TextEditingController(); +// Contact? selectedContact; +// +// List contactsList = []; +// RxList filteredContacts = [].obs; +// +// late InputField searchContacts; +// +// @override +// void onInit() { +// super.onInit(); +// _loadContacts(); +// } +// +// @override +// onReady() { +// super.onReady(); +// // searchContacts.controller?.addListener(() { +// // if (searchContacts.getCustomText().isEmpty) { +// // filteredContacts.assignAll(contactsList); +// // } else { +// // filteredContacts.value = contactsList.where((element) => element.name.first == searchContacts.getCustomText() || element.name.last == searchContacts.getCustomText()).toList(); +// // } +// // }); +// } +// +// Future _loadContacts() async { +// /// Check if the app has permission to access contacts +// var status = await Permission.contacts.status; +// // showLoader(); +// if (status.isGranted) { +// /// Permission is granted, load contacts +// try { +// contactsList = await FlutterContacts.getContacts(withProperties: true, withAccounts: true, withPhoto: true, sorted: true, withThumbnail: true); +// filteredContacts.assignAll(contactsList); +// hideLoader(); +// } catch (e) { +// print('Error loading contacts: $e'); +// hideLoader(); +// } +// } else { +// /// Permission is not granted, request permission +// await _requestPermissions(); +// hideLoader(); +// } +// hideLoader(); +// } +// +// Future _requestPermissions() async { +// /// Request contacts permission +// var status = await Permission.contacts.request(); +// if (!status.isGranted) { +// Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textPermissionDenied)); +// } else { +// /// Permission granted, load contacts +// await _loadContacts(); +// } +// } +// +// /// Function to filter contacts based on search query +// void filterContacts(String searchText) { +// if (searchText.isEmpty) { +// filteredContacts.assignAll(contactsList); +// } else { +// searchText = searchText.toLowerCase(); +// filteredContacts.assignAll(contactsList.where((contact) { +// // Check if either name or phone number matches the search text +// bool matchesName = contact.name.first.toLowerCase().contains(searchText) || +// (contact.name.last != null && contact.name.last!.toLowerCase().contains(searchText)); +// +// bool matchesPhoneNumber = false; +// for (var number in contact.phones) { +// if (number.number.toLowerCase().contains(searchText)) { +// matchesPhoneNumber = true; +// break; +// } +// } +// +// return matchesName || matchesPhoneNumber; +// }).toList()); +// } +// } +// /// Phone number pattern +// String flattenPhoneNumber(String phoneStr) { +// return phoneStr.replaceAllMapped(RegExp(r'^(\+)|\D'), (Match m) { +// return m[0] == "+" ? "+" : ""; +// }); +// } +// +// void handleContactSelection(Contact selectedContact) { +// Get.back(result: {AppConstants.SELECTED_CONTACT: selectedContact}); +// } +// +// } diff --git a/lib/app/modules/contacts_screen/views/contacts_screen_view.dart b/lib/app/modules/contacts_screen/views/contacts_screen_view.dart new file mode 100644 index 0000000..9a46c72 --- /dev/null +++ b/lib/app/modules/contacts_screen/views/contacts_screen_view.dart @@ -0,0 +1,107 @@ +// import 'package:flutter/material.dart'; +// import 'package:get/get.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_no_record.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_colors.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_dimensions.dart'; +// +// import '../../../custom_widgets/custom_app_bar.dart'; +// import '../controllers/contacts_screen_controller.dart'; +// +// class ContactsScreenView extends GetView { +// const ContactsScreenView({Key? key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// String className = runtimeType.toString().split('.').last; +// return Scaffold( +// appBar: DashBoardAppBar( +// title: TranslationKeys.makeTranslation("Contacts"), +// onBackButtonPressed: () { +// Get.back(); +// }, +// ), +// body: Padding( +// padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// TextField( +// style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), +// decoration: const InputDecoration( +// suffixIconColor: AppColors.colorPrimary, +// filled: true, +// fillColor: AppColors.colorGrey200, +// enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: Colors.transparent)), +// border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: AppColors.colorGrey500)), +// focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, style: BorderStyle.solid, color: Colors.transparent)), +// hintText: 'Search contact number', +// hintStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorGrey500), +// suffixIcon: Icon(Icons.search_rounded, size: 22), +// ), +// onChanged: (value) { +// controller.filterContacts(value); +// }), +// const SizedBox(height: 20), +// Text(TranslationKeys.makeTranslation("Contacts"), style: Theme.of(context).textTheme.bodyMedium), +// const SizedBox(height: 10), +// Obx(() { +// return controller.filteredContacts.isEmpty +// ? const Center( +// child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), +// ) +// : Expanded( +// flex: 2, +// child: ListView.builder( +// itemCount: controller.filteredContacts.length, +// itemBuilder: (context, index) { +// final contact = controller.filteredContacts[index]; +// final phoneNumber = contact.phones.isNotEmpty ? contact.phones[0].number : 'No phone number'; +// return ListTile( +// onTap: () { +// controller.handleContactSelection(contact); +// }, +// title: Text(contact.displayName), +// subtitle: Text( +// phoneNumber, +// style: Theme.of(context).textTheme.bodySmall, +// ), +// leading: CircleAvatar( +// backgroundColor: AppColors.colorPrimary, +// backgroundImage: contact.photo != null ? MemoryImage(contact.photo!) : null, +// child: Text( +// getInitials(contact.displayName), +// style: Theme.of(context).textTheme.titleSmall?.copyWith(color: Colors.white), +// ), +// ), +// ); +// }, +// ), +// ); +// }), +// ], +// ), +// ), +// ); +// } +// +// String getInitials(String fullName) { +// if (fullName.isEmpty) { +// return ""; +// } +// +// // Split the full name into words +// List nameParts = fullName.trim().split(' '); +// +// // Check if there's at least a first and last name +// if (nameParts.length < 2) { +// return fullName.substring(0, 1).toUpperCase(); // Get first character +// } +// +// // Get first characters of first and last name +// String firstInitial = nameParts[0].substring(0, 1).toUpperCase(); +// String lastInitial = nameParts[nameParts.length - 1].substring(0, 1).toUpperCase(); +// +// return firstInitial + lastInitial; +// } +// } diff --git a/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart b/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart new file mode 100644 index 0000000..0b7adbf --- /dev/null +++ b/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/create_transaction_pin_controller.dart'; + +class CreateTransactionPinBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CreateTransactionPinOTPControllerTest(), + ); + } +} diff --git a/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart b/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart new file mode 100644 index 0000000..178e139 --- /dev/null +++ b/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../routes/app_pages.dart'; + + +class CreateTransactionPinOTPControllerTest extends GetxController { + final repository = Get.find(); + + TextEditingController newTransactionPinController = TextEditingController(); + TextEditingController confirmTransactionPinController = TextEditingController(); + + void validateAndSendRequest() async { + if (newTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (confirmTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (newTransactionPinController.text != confirmTransactionPinController.text) { + Toasty.error("Transaction Pin did not match"); + return; + } + + CreateTransactionPinOTPRequest request = CreateTransactionPinOTPRequest( + newTransPincode: newTransactionPinController.text, + pinType: AppConstants.PIN_TYPE_Transaction, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequire: false, + ); + + ServerResponse response = await repository.createTransactionPinOTP(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + Get.toNamed( + Routes.CREATE_TRANSACTION_PIN_OTP, + arguments: { + 'transactionPin': newTransactionPinController.text, + 'confirmTransactionPin': confirmTransactionPinController.text, + 'isSomething': false, + AppConstants.CREATE_TRANSACTION_PIN_OTP: request, + }, + ); + clearController(); + } + + void clearController() { + newTransactionPinController.clear(); + confirmTransactionPinController.clear(); + } +} diff --git a/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart b/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart new file mode 100644 index 0000000..20f5406 --- /dev/null +++ b/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/create_transaction_pin_controller.dart'; + +class CreateTransactionPinView extends GetView { + const CreateTransactionPinView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textCreateTransactionPin), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPleaseCreatenewtransactionpin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 20), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.newTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + textInputAction: TextInputAction.done, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 20), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.confirmTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + textInputAction: TextInputAction.done, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ); + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart b/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart new file mode 100644 index 0000000..161333c --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/create_transaction_pin_otp_controller.dart'; + +class CreateTransactionPinOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CreateTransactionPinOtpController(), + ); + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart b/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart new file mode 100644 index 0000000..472dc89 --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../models/CreateTransactionPinRequest.dart'; +import '../../../routes/app_pages.dart'; + + +class CreateTransactionPinOtpController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + late String newTransactionPin; + late String confirmTransactionPin; + CreateTransactionPinOTPRequest createTransactionPinOTPRequest = CreateTransactionPinOTPRequest(); + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + late bool isSomething; + late final request; + + @override + void onReady() { + super.onReady(); + var arguments = Get.arguments; + newTransactionPin = arguments['transactionPin']; + confirmTransactionPin = arguments['confirmTransactionPin']; + isSomething = arguments['isSomething']; + createTransactionPinOTPRequest = arguments[AppConstants.CREATE_TRANSACTION_PIN_OTP]; + + dp("newTransactionPin>>>>", newTransactionPin); + dp("confirmTransactionPin>>>>", confirmTransactionPin); + } + + void validateAndSendRequest() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + CreateTransactionPinRequest request = CreateTransactionPinRequest( + channelCode: RequestConstants.channelCode, + pctCstycode: RequestConstants.pctCstycode, + porOrgacode: RequestConstants.porOrgacode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + obpPincode: pinPutController.text, + pinType: AppConstants.PIN_TYPE_Transaction, + ); + + ServerResponse response = await repository.createTransactionPin(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + clearController(); + CustomDialog.showSuccessDialog( + // title: "Congratulations!", + description: "Your Transaction pin successfully ! An send email and message have been sent to you.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.createTransactionPinOTP(createTransactionPinOTPRequest); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void clearController() { + pinPutController.clear(); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart b/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart new file mode 100644 index 0000000..b46417b --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/create_transaction_pin_otp_controller.dart'; + +class CreateTransactionPinOtpView extends GetView { + const CreateTransactionPinOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart b/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart new file mode 100644 index 0000000..f3833b4 --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/dail_transaction_limit_controller.dart'; + +class DailTransactionLimitBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DailTransactionLimitController(), + ); + } +} diff --git a/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart b/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart new file mode 100644 index 0000000..7815f9b --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; + +class DailTransactionLimitController extends GetxController { + late InputField newDailyLimit; + late InputField debitCardNumber; + late InputField atmPin; +} diff --git a/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart b/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart new file mode 100644 index 0000000..b89ee7c --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/dail_transaction_limit_controller.dart'; + +class DailTransactionLimitView extends GetView { + const DailTransactionLimitView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textTransactionLimit), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20.0), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey350), + borderRadius: const BorderRadius.all(Radius.circular(8.0)), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 30, + child: SvgPicture.asset(AppAssets.ic_money_management, height: 30, width: 30), + ), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textOldLimit), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCurrentDailyLimit), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + ], + ), + ), + ), + const SizedBox(height: 5), + controller.newDailyLimit = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}SetDailyLimitAmount"), + controller: FormFieldConstants.instance().getController("${className}SetDailyLimitAmount"), + // hintText: "Enter username", + labelText: "Set Daily Limit Amount", + keyboardType: TextInputType.text, + ), + controller.debitCardNumber = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}DebitCardNumber"), + controller: FormFieldConstants.instance().getController("${className}DebitCardNumber"), + labelText: "Debit Card Number", + keyboardType: TextInputType.text, + ), + controller.atmPin = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}ATMPin"), + controller: FormFieldConstants.instance().getController("${className}ATMPin"), + labelText: "ATMPin", + keyboardType: TextInputType.text, + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textMaximumLengthContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLimitNoteContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + ], + ), + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + Get.offAndToNamed(Routes.APP_SETTING); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDone), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // Get.offAndToNamed(Routes.APP_SETTING); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDone), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart b/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart new file mode 100644 index 0000000..c6b4df4 --- /dev/null +++ b/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/dashboard_screen_controller.dart'; + +class DashboardScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DashboardScreenController(), + ); + } +} diff --git a/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart b/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart new file mode 100644 index 0000000..3fa9793 --- /dev/null +++ b/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart @@ -0,0 +1,129 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../models/dashboard_response_model.dart'; +import '../../u_received/controllers/u_received_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; + +RxInt transitionUpdate = RxInt(0); + +class DashboardScreenController extends GetxController { + BuildContext context = Get.context as BuildContext; + + final AppRepositories repository = Get.find(); + + RxBool isDrawerOpen = false.obs; + int curentIndex = 0; + + RxList depositeAccount = [DepositAccount.empty()].obs; + final ZoomDrawerController zoomController = ZoomDrawerController(); + + /// Change Icon method + void toggleDrawer() { + isDrawerOpen.value = !isDrawerOpen.value; + if (isDrawerOpen.value) { + zoomController.open!(); + } else { + zoomController.close!(); + } + } + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + fetchDepositAccounts(); + fetchExchangeRates(); + + transitionUpdate.listen( + (p0) { + fetchDepositAccounts(); + fetchExchangeRates(); + }, + ); + } + + @override + void onInit() { + super.onInit(); + // fingerPrintLogin(); + } + + // Future fingerPrintLogin() async { + // String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + // if (info.isNotEmpty) { + // FingerPrintInfo fingerPrintInfo = FingerPrintInfo.fromMap(jsonDecode(info)); + // if (fingerPrintInfo.cmpUserId != SessionCache.instance.userInfo.cmpUserId || fingerPrintInfo.cmpCustpassword != SessionCache.instance.userInfo.cmpCustpassword) { + // // SessionCache.instance.fingerPrintController.clearFromDB(); + // } + // } + // } + + Future fetchDepositAccounts() async { + ServerResponse response = await repository.fetchAccountDetails(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + DashBoardResponseModel dashboardResponse = DashBoardResponseModel.fromMap(response.response); + SessionCache.instance.depositAccountList.value = dashboardResponse.deposit; + depositeAccount.assignAll(SessionCache.instance.depositAccountList); + } + + Future fetchExchangeRates() async { + ServerResponse response = await repository.fetchExchangeRate(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + SessionCache.instance.exchangeRateList.value = List.from(((response.response ?? []) as List).map((x) => ExchangeRate.fromMap(x))); + + SessionCache.instance.exchangeRateList.insert( + 0, + ExchangeRate( + petExrtdesc: "Official Rate", + pcrCurrcode: "586", + perEratrateact: 1.0, + petExrtcode: "3", + perEratdate: "2024-06-27", + pcrCurrshort: "PKR", + porOrgacode: "0006", + pcrCurrdesc: "Pakistani Rupees", + )); + } + + updatePage(int index) { + Get.put(UReceivedController()); + + curentIndex = index; + + update(); + if (index != 1) { + Get.find().clearTransaction(); + } + } + + /// Get Flag fucntion + String getFlagWithCurrencyCode(currencyCodeInt) { + if (currencyCodeInt == "586") { + return "assets/uco/icons/ic_pakistan.png"; + } else if (currencyCodeInt == "997") { + return "assets/uco/icons/usa.png"; + } else { + return "assets/uco/icons/euro_flag.png"; + } + + // else { + // return "assets/uco/icons/default_flag.png"; + // } + } +} diff --git a/lib/app/modules/dashboard/views/dashboard_screen_view.dart b/lib/app/modules/dashboard/views/dashboard_screen_view.dart new file mode 100644 index 0000000..3fa8c9f --- /dev/null +++ b/lib/app/modules/dashboard/views/dashboard_screen_view.dart @@ -0,0 +1,78 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:uco_mobile_poc/app/modules/dashboard/views/shared/drawer_data.dart'; +import 'package:uco_mobile_poc/app/modules/dashboard/views/shared/home_page.dart'; + +class DashboardScreenView extends StatefulWidget { + const DashboardScreenView({Key? key}) : super(key: key); + + @override + State createState() => _DashBoardViewState(); +} + +class _DashBoardViewState extends State with SingleTickerProviderStateMixin { + late AnimationController _animationController; + + bool _isDoubleTapped = false; + + @override + void initState() { + super.initState(); + + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200), + ); + } + + void toggleAnimation() { + _animationController.isDismissed ? _animationController.forward() : _animationController.reverse(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + Future handleDoubleTab() async { + if (_isDoubleTapped) { + return true; // Allow the app to be exited + } else { + // Set _isDoubleTapped to true and display a message + setState(() { + _isDoubleTapped = true; + }); + // Reset _isDoubleTapped after 2 seconds + Timer(const Duration(seconds: 2), () { + setState(() { + _isDoubleTapped = false; + }); + }); + // Prevent the app from being exited + return false; + } + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => handleDoubleTab(), + child: SafeArea( + child: Material( + child: ZoomDrawer( + menuScreen: DrawerData(), + mainScreen: MyHomePage(), + borderRadius: 24.0, + showShadow: true, + angle: 0.0, + openCurve: Curves.fastOutSlowIn, + closeCurve: Curves.easeInBack, + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart b/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart new file mode 100644 index 0000000..065c3cc --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../../../../res/app_colors.dart'; + + +class BottomSheetIcon extends StatelessWidget { + String title; + Function() onTap; + final String imageProvider; + double? width; + double? height; + + BottomSheetIcon( + {super.key, + required this.title, + required this.imageProvider, + required this.onTap, + this.height, + this.width}); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + imageProvider, + width: width, + height: height, + ), + const SizedBox(height: 3), + Text( + title, + style: Theme.of(context) + .textTheme + .labelSmall! + .copyWith(fontWeight: FontWeight.w500, color: AppColors.white), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/drawer_data.dart b/lib/app/modules/dashboard/views/shared/drawer_data.dart new file mode 100644 index 0000000..37e956b --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/drawer_data.dart @@ -0,0 +1,344 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/app_contants.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../core/utils/SessionCache.dart'; +import '../../../../custom_widgets/custom_dialog.dart'; +import '../../../../custom_widgets/custom_label.dart'; +import '../../../../custom_widgets/custom_toasty.dart'; +import '../../../../custom_widgets/responsive_widget.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../../user_profile/controllers/user_profile_controller.dart'; +import '../../controllers/dashboard_screen_controller.dart'; + +class DrawerData extends GetView { + final Function()? toggleAnimation; + + DrawerData({super.key, this.toggleAnimation}); + UserProfileController userProfileController = Get.put(UserProfileController()); + + @override + Widget build(BuildContext context) { + List drawerList = DrawerList.getItemsList(context); + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(25), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + InkWell( + onTap: () { + // dp("Profile Pictures========", profilePic); + }, + child: Obx(() { + return CircleAvatar( + radius: 30, + backgroundColor: AppColors.colorPrimary, + child: Padding( + padding: const EdgeInsets.all(8), // Border radius + child: userProfileController.profilePic.isNotEmpty + ? ClipOval( + child: Image.memory( + base64Decode(userProfileController.profilePic.value), + height: 40, + width: 40, + fit: BoxFit.cover, + ), + ) + : const Icon(Icons.person, color: AppColors.white), + ), + ); + }), + ), + const SizedBox(width: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(SessionCache.instance.userInfo.name, style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 2), + Text(SessionCache.instance.userInfo.cmpCustlastlogin != null ? SessionCache.instance.userInfo.cmpCustlastlogin : "N/A", + /*TranslationKeys.makeTranslation( + TranslationKeys.textAccountSession),*/ + style: Theme.of(context).textTheme.bodyMedium), + ], + ), + ], + ), + const SizedBox(height: 20), + ListView.builder( + itemCount: drawerList.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (ctx, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: InkWell(onTap: () {}, child: Text(drawerList[index].label, style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w600))), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + itemCount: drawerList[index].drawerList.length, + shrinkWrap: true, + itemBuilder: (ctx, innerIndex) { + return Padding(padding: const EdgeInsets.symmetric(vertical: 0), child: getDrawerWidget(drawerList[index].drawerList[innerIndex], context)); + }), + const SizedBox(height: 10) + ], + ); + }), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + Widget getDrawerWidget(DrawerItem item, BuildContext context) { + return InkWell( + onTap: () { + switch (item.id) { + // case AppConstants.ID_MY_ACCOUNT: + // Get.toNamed(Routes.MY_ACCOUNT); + // break; + case AppConstants.ID_BILL_MANAGEMENT: + Get.toNamed(Routes.BILL_MANAGEMENT); + break; + case AppConstants.ID_CHEQUE_MANAGEMENT: + Get.toNamed(Routes.CHEQUE_MANAGEMENT); + break; + case AppConstants.ID_INTERNAL_TRANSACTION: + Get.toNamed(Routes.INTERNAL_ACCOUNT_TRANS); + break; + + case AppConstants.ID_BENEFICIARY_MANAGEMENT: + Get.toNamed(Routes.BENEFICIARY_MANAGEMENT); + break; + case AppConstants.ID_AGENT_LOCATION: + if (Platform.isIOS) { + Toasty.error("Coming soon"); + } else { + Get.toNamed(Routes.AGENT_LOCATION); + } + + break; + case AppConstants.ID_ACCOUNT_STATEMENT: + Get.toNamed(Routes.ACCOUNT_STATEMENT); + break; + case AppConstants.ID_SUPPORT: + showCutomBottomSheet(supportBottomSheet(context)); + break; + case AppConstants.ID_USER_PROFILE: + Get.toNamed(Routes.USER_PROFILE); + break; + case AppConstants.ID_PRIVACY_POLICY: + Get.toNamed(Routes.PRIVACY_POLICY); + break; + case AppConstants.ID_USER_ACTIVITY: + Get.toNamed(Routes.USER_ACTIVITY); + break; + case AppConstants.ID_APP_SETTING: + Get.toNamed(Routes.APP_SETTING); + break; + case AppConstants.ID_ABOUT_US: + Get.toNamed(Routes.ABOUT_US); + break; + case AppConstants.ID_CAREER: + Get.toNamed(Routes.CAREER); + break; + case AppConstants.ID_LOGOUT: + { + CustomDialog.showLogoutDialog( + context: context, + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + ); + } + break; + default: + print("Print thisi is isiisisisisisisis"); + } + }, + child: Container( + padding: const EdgeInsets.all(8), + child: Row( + children: [ + SvgPicture.asset( + item.icon, + height: 20, + width: 20, + color: AppColors.colorPrimary, + ), + const SizedBox(width: 15), + Text(item.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 15, fontWeight: FontWeight.w400)), + ], + ), + ), + ); + } + + /// Drawer Support Bottom Sheet Widget + + Container supportBottomSheet(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + return Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset(AppAssets.ic_cross, height: 15, width: 15), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorText, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset("${supportBottomSheetList[index].image}", height: 50, width: 50), + const SizedBox(height: 20), + Center( + child: LabelText('${supportBottomSheetList[index].title}', style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} + +class DrawerList { + final String label; + final List drawerList; + + DrawerList(this.label, this.drawerList); + + static List getItemsList(BuildContext context) { + return [ + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textManage), [ + // DrawerItem( + // AppConstants.ID_MY_ACCOUNT, + // AppAssets.ic_user, + // TranslationKeys.makeTranslation(TranslationKeys.textMyAccount), + // () => Routes.USER_ACTIVITY), + DrawerItem(AppConstants.ID_BILL_MANAGEMENT, AppAssets.ic_bill, TranslationKeys.makeTranslation(TranslationKeys.textBillManagement), () => Routes.BILL_MANAGEMENT), + DrawerItem(AppConstants.ID_CHEQUE_MANAGEMENT, AppAssets.ic_cheque_management, TranslationKeys.makeTranslation(TranslationKeys.textChequeManagement), () => Routes.CHEQUE_MANAGEMENT), + DrawerItem(AppConstants.ID_INTERNAL_TRANSACTION, AppAssets.ic_u_cash, TranslationKeys.makeTranslation(TranslationKeys.textInternalAccountTransaction), () => Routes.U_SEND), + DrawerItem(AppConstants.ID_BENEFICIARY_MANAGEMENT, AppAssets.ic_u_recive, TranslationKeys.makeTranslation(TranslationKeys.textBeneficiaryManagement), () => Routes.U_RECEIVED), + DrawerItem(AppConstants.ID_AGENT_LOCATION, AppAssets.ic_location, TranslationKeys.makeTranslation(TranslationKeys.textAgentLocation), () => Routes.AGENT_LOCATION), + DrawerItem(AppConstants.ID_ACCOUNT_STATEMENT, AppAssets.ic_money_management, TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), () => Routes.ACCOUNT_STATEMENT), + ]), + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textSupport), [ + DrawerItem(AppConstants.ID_SUPPORT, AppAssets.ic_customer_service, TranslationKeys.makeTranslation(TranslationKeys.textSupport), () {}), + DrawerItem(AppConstants.ID_USER_PROFILE, AppAssets.ic_user, TranslationKeys.makeTranslation(TranslationKeys.textUserProfile), () => Routes.USER_PROFILE), + DrawerItem(AppConstants.ID_USER_ACTIVITY, AppAssets.ic_activity, TranslationKeys.makeTranslation(TranslationKeys.textUserActivity), () => Routes.USER_ACTIVITY), + DrawerItem(AppConstants.ID_ABOUT_US, AppAssets.ic_user, TranslationKeys.makeTranslation(TranslationKeys.textAboutUs), () => Routes.ABOUT_US), + DrawerItem(AppConstants.ID_APP_SETTING, AppAssets.ic_setting, TranslationKeys.makeTranslation(TranslationKeys.textAppSetting), () => Routes.APP_SETTING), + DrawerItem(AppConstants.ID_CAREER, AppAssets.ic_sub_accounts, TranslationKeys.makeTranslation(TranslationKeys.textCareer), () => Routes.CAREER), + ]), + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), [ + DrawerItem( + AppConstants.ID_LOGOUT, + AppAssets.ic_logout, + TranslationKeys.makeTranslation(TranslationKeys.textLogout), + () {}, + ), + ]), + ]; + } +} + +class DrawerItem { + final String id; + final String icon; + final String title; + Function()? onTap; + + DrawerItem(this.id, this.icon, this.title, this.onTap); +} diff --git a/lib/app/modules/dashboard/views/shared/home_page.dart b/lib/app/modules/dashboard/views/shared/home_page.dart new file mode 100644 index 0000000..9d8f124 --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/home_page.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/dashboard_screen_controller.dart'; +import 'drawer_data.dart'; +import 'main_dash_board.dart'; + +class MyHomePage extends StatelessWidget { + MyHomePage({super.key}); + + final DashboardScreenController dashBoardController = Get.put(DashboardScreenController()); + final MenuController menuController = Get.put(MenuController()); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + centerTitle: true, + elevation: 0.0, + title: Text( + TranslationKeys.makeTranslation(TranslationKeys.textOverView), + style: Theme.of(context).textTheme.displaySmall!.copyWith( + color: AppColors.colorSecondary, + fontSize: 23, + fontFamily: "Poppins", + fontWeight: FontWeight.w500, + ), + ), + leading: Obx(() { + return Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + dashBoardController.toggleDrawer(); + }, + child: Icon( + dashBoardController.isDrawerOpen.value ? Icons.close : Icons.menu, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ); + }), + actions: [ + Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + // dashBoardController.fetchDepositAccounts(); + // dashBoardController.fetchExchangeRates(); + }, + child: const Icon( + Icons.refresh_outlined, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ), + Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + Get.toNamed(Routes.NOTIFICATIONS); + }, + child: const Icon( + Icons.notifications_none_outlined, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ), + const SizedBox(width: 10) + ], + ), + body: ZoomDrawer( + controller: dashBoardController.zoomController, + menuScreen: DrawerData(), + mainScreen: DashBoardWithAllAccounts(), + openCurve: Curves.fastOutSlowIn, + showShadow: false, + slideWidth: MediaQuery.of(context).size.width * 0.7, + isRtl: Directionality.of(context) == TextDirection.rtl, + mainScreenTapClose: false, + mainScreenOverlayColor: Colors.transparent, + borderRadius: 10, + angle: 0.0, + menuScreenWidth: double.infinity, + moveMenuScreen: true, + style: DrawerStyle.defaultStyle, + //drawerShadowsBackgroundColor: Colors.yellow, + mainScreenAbsorbPointer: false, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 10, + blurRadius: 4, + offset: const Offset(3, 3), // changes position of shadow + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/main_dash_board.dart b/lib/app/modules/dashboard/views/shared/main_dash_board.dart new file mode 100644 index 0000000..dc49c24 --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/main_dash_board.dart @@ -0,0 +1,905 @@ +// import 'package:flutter/material.dart'; +// +// import 'package:get/get.dart'; +// import 'package:uco_ciihive/app/core/constants/app_assets.dart'; +// import 'package:uco_ciihive/app/core/constants/translation_keys.dart'; +// import 'package:uco_ciihive/app/modules/dashboard/controllers/dashboard_screen_controller.dart'; +// import 'package:uco_ciihive/app/modules/user_profile/controllers/user_profile_controller.dart'; +// import 'package:uco_ciihive/app/res/app_colors.dart'; +// import 'package:uco_ciihive/app/res/app_dimensions.dart'; +// import 'package:uco_ciihive/app/routes/app_pages.dart'; +// +// import 'bottom_sheet_icon.dart'; +// +// class DashBoardWithAllAccounts extends GetView { +// late MenuController? menuController; +// +// DashBoardWithAllAccounts({super.key, this.menuController}); +// +// final DashboardScreenController dashBoardController = Get.find(); +// +// @override +// Widget build(BuildContext Get.context!) { +// controller.Get.context! = Get.context!; +// return Scaffold( +// floatingActionButton: Padding( +// padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30), +// child: SpeedDial( +// openBackgroundColor: AppColors.colorButton, +// closedBackgroundColor: AppColors.colorPrimaryLight, +// labelsBackgroundColor: AppColors.colorButton, +// labelsStyle: Theme.of(Get.context!).textTheme.bodyMedium?.copyWith(color: AppColors.colorPrimary), +// speedDialChildren: [ +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(2.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.DIRECT_PAYMENT); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.NEW_BENEFICIARY); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// // Get.toNamed(Routes.OWN_TRANSFER); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.ZAKAT); +// }, +// ), +// ], +// child: CustomText(TranslationKeys.makeTranslation(TranslationKeys.textHelp), style: Theme.of(Get.context!).textTheme.titleSmall?.copyWith(fontSize: 11, color: AppColors.colorSecondary)), +// ), +// ), +// body: Column( +// children: [ +// Expanded( +// child: SingleChildScrollView( +// child: Column( +// children: [ +// Stack( +// children: [ +// Container( +// height: 60, +// color: AppColors.colorPrimary, +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 20), +// child: CircleAvatar( +// radius: 40.0, +// child: SvgPicture.asset( +// AppAssets.lg_round_uc_logo, +// height: 100, +// width: 100, +// fit: BoxFit.cover, +// ), +// ), +// ), +// ), +// ], +// ), +// SizedBox(height: 10), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textDashboardWelcomeUser), style: Theme.of(Get.context!).textTheme.titleMedium), +// SizedBox(height: 10), +// Stack( +// children: [ +// Align( +// alignment: Alignment.center, +// child: Container( +// height: 230, +// width: 188, +// decoration: BoxDecoration( +// color: AppColors.colorGrey100, +// border: Border.all(color: AppColors.colorText.withOpacity(0.1), width: 1), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 15.0), +// child: Container( +// height: 225, +// width: 188, +// decoration: BoxDecoration( +// color: AppColors.colorGrey200, +// border: Border.all(color: AppColors.colorText.withOpacity(0.2), width: 1), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.all(30.0), +// child: Container( +// height: 200, +// width: 212, +// decoration: BoxDecoration( +// color: AppColors.colorGrey50, +// border: Border.all(color: AppColors.colorButton, width: 2), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 40.0), +// child: Container( +// height: 179, +// width: 190, +// decoration: BoxDecoration( +// color: AppColors.colorGrey50, +// border: Border.all(color: AppColors.colorPrimary, width: 2), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// child: Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20), +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableFunds), style: Theme.of(Get.context!).textTheme.bodySmall), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableBalance), style: Theme.of(Get.context!).textTheme.titleLarge), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableBalanceInWords), style: Theme.of(Get.context!).textTheme.bodySmall), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textAccountNumber), style: Theme.of(Get.context!).textTheme.bodySmall), +// ], +// ), +// ), +// ), +// ), +// ), +// ], +// ), +// SizedBox(height: 5), +// Stack( +// children: [ +// InkWell( +// onTap: () { +// Get.toNamed(Routes.TRANSACTION_HISTORY); +// }, +// child: Padding( +// padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), +// child: Container( +// color: AppColors.colorGrey300, +// child: Row( +// children: [ +// Column(children: [ +// Container( +// decoration: const BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.zero, +// ), +// child: Padding( +// padding: const EdgeInsets.all(20.0), +// child: SvgPicture.asset(AppAssets.img_debet, color: AppColors.colorSecondary), +// ), +// ) +// ]), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ +// CustomText( +// "Current Account", +// style: Theme.of(Get.context!).textTheme.titleSmall, +// ), +// SizedBox(height: 5), +// CustomText( +// "022379122*****95", +// style: Theme.of(Get.context!).textTheme.bodySmall, +// ), +// ]), +// ), +// ], +// ), +// ), +// ), +// ), +// Positioned( +// top: 20, +// right: 20, +// child: Align( +// alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, +// child: Transform( +// alignment: Alignment.center, +// transform: Matrix4.rotationY(Directionality.of(Get.context!) == TextDirection.rtl ? 3.14159 : 0), +// child: SizedBox( +// height: 40, +// width: 40, +// child: SvgPicture.asset( +// fit: BoxFit.cover, +// AppAssets.img_round_dashboard_card, +// height: 35, +// width: 35, +// )), +// )), +// ), +// ], +// ), +// SizedBox(height: 20), +// Stack( +// children: [ +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), +// child: Container( +// color: AppColors.colorGrey300, +// child: Row( +// children: [ +// Column(children: [ +// Container( +// decoration: const BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.zero, +// ), +// child: Padding( +// padding: const EdgeInsets.all(20.0), +// child: SvgPicture.asset(AppAssets.img_debet, color: AppColors.colorSecondary), +// ), +// ) +// ]), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ +// CustomText( +// "Current Account", +// style: Theme.of(Get.context!).textTheme.titleSmall, +// ), +// SizedBox(height: 5), +// CustomText( +// "022379122*****95", +// style: Theme.of(Get.context!).textTheme.bodySmall, +// ), +// ]), +// ), +// ], +// ), +// ), +// ), +// Positioned( +// top: 20, +// right: 20, +// child: Align( +// alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, +// child: Transform( +// alignment: Alignment.center, +// transform: Matrix4.rotationY(Directionality.of(Get.context!) == TextDirection.rtl ? 3.14159 : 0), +// child: SizedBox( +// height: 40, +// width: 40, +// child: SvgPicture.asset( +// fit: BoxFit.cover, +// AppAssets.img_round_dashboard_card, +// height: 35, +// width: 35, +// )), +// )), +// ), +// ], +// ), +// ], +// ), +// ), +// ), +// Container( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Stack( +// alignment: Alignment.bottomCenter, +// children: [ +// Container( +// padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10), +// margin: EdgeInsets.only(bottom: 10), +// width: double.infinity, +// decoration: BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.all( +// Radius.circular(10), +// ), +// ), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// SizedBox(width: 20), +// /* const SizedBox()*/ +// ], +// ), +// ), +// ], +// ), +// ) +// ], +// ), +// ); +// } +// } +// ======= + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../core/utils/SessionCache.dart'; +import '../../../../core/utils/logs_utils.dart'; +import '../../../../custom_widgets/custom_no_record.dart'; +import '../../../../custom_widgets/custom_text.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../../speed_dial/src/simple_speed_dial.dart'; +import '../../../u_received/views/u_received_view.dart'; +import '../../../u_send/views/u_send_view.dart'; +import '../../controllers/dashboard_screen_controller.dart'; +import 'bottom_sheet_icon.dart'; + +class DashBoardWithAllAccounts extends GetView { + late MenuController? menuController; + + DashBoardWithAllAccounts({super.key, this.menuController}); + + final DashboardScreenController dashBoardController = Get.find(); + + List widgetList = [ + const DashBoardPage(), + const USendView(showAppBar: false), + const UReceivedView(showAppBar: false), + const Center( + child: CustomNoRecord(title: "No Record Found", + description: "We couldn't find any activity at this moment"), + ) + ]; + + @override + Widget build(BuildContext context) { + controller.context = context; + + return KeyboardVisibilityBuilder(builder: (context, isKeyboardOpen) { + dp("OPen is", isKeyboardOpen); + + return Scaffold( + resizeToAvoidBottomInset: false, + floatingActionButton: isKeyboardOpen ? null : mainFloatingButton(), + floatingActionButtonLocation: FloatingActionButtonLocation.endDocked, + bottomNavigationBar: isKeyboardOpen + ? null + : Container( + height: 55, + clipBehavior: Clip.none, + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 0), + margin: const EdgeInsets.only(bottom: 10, right: 20, left: 20), + decoration: const BoxDecoration( + color: AppColors.colorPrimary, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textHome), + imageProvider: AppAssets.ic_home_icon, + onTap: () { + dp("Click", " home dash board"); + controller.updatePage(0); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textUSend), + imageProvider: AppAssets.ic_u_cash, + onTap: () { + dp("Click", " home dash board"); + controller.updatePage(1); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textReceived), + imageProvider: AppAssets.ic_u_recive, + onTap: () { + controller.updatePage(2); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textUShop), + imageProvider: AppAssets.ic_u_shop, + onTap: () { + controller.fetchDepositAccounts(); + + controller.fetchExchangeRates(); + + controller.updatePage(3); + }, + width: 25, + height: 25, + ), + const SizedBox(width: 20), + /* const SizedBox()*/ + ], + ), + ), + body: GetBuilder( + builder: (controller) => widgetList[controller.curentIndex], + ), + ); + }); + } + + Widget mainFloatingButton() { + return SpeedDial( + openBackgroundColor: AppColors.colorButton, + closedBackgroundColor: AppColors.colorPrimaryLight, + labelsBackgroundColor: AppColors.colorButton, + labelsStyle: Get.context!.textTheme.bodyMedium?.copyWith( + color: AppColors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + speedDialChildren: [ + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textBillManagement), + child: SvgPicture.asset(AppAssets.ic_bill), + onPressed: () { + Get.toNamed(Routes.BILL_MANAGEMENT); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), + child: SvgPicture.asset(AppAssets.ic_money_management), + onPressed: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textUserActivity), + child: SvgPicture.asset(AppAssets.ic_activity), + onPressed: () { + Get.toNamed(Routes.USER_ACTIVITY); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textAddBeneficiary), + child: SvgPicture.asset(AppAssets.ic_u_recive, color: AppColors.colorPrimary), + onPressed: () { + Get.toNamed(Routes.BENEFICIARY_MANAGEMENT); + }, + ), + ], + child: SvgPicture.asset( + AppAssets.sending_icon, + )); + } +} + +class DashBoardPage extends StatelessWidget { + const DashBoardPage({super.key}); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Obx(() { + return Column( + children: [ + controller.depositeAccount.isEmpty + ? const Center( + child: Text("Data not found please try again"), + ) + : Expanded( + child: Column( + children: [ + Stack( + fit: StackFit.passthrough, + clipBehavior: Clip.none, + children: [ + Container( + height: 60, + color: AppColors.colorPrimary, + ), + Align( + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.only(top: 20), + child: SvgPicture.asset(AppAssets.ic_dashboard_logo, height: 89, width: 79, fit: BoxFit.cover), + ), + ), + const Positioned(bottom: -10, left: 0, right: 0, child: AddMoneyAndKyc()), + ], + ), + const SizedBox(height: 27), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: CustomText( + "Welcome ${SessionCache.instance.userInfo.name}", + style: context.textTheme.titleMedium!.copyWith(fontSize: 21, fontWeight: FontWeight.w400), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 30), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ...controller.depositeAccount + .map((depositAccount) => InkWell( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT, arguments: {"accountNumber": depositAccount.mbmBkmsnumber}); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 2), // Adjust for shadow position (x, y) + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 0), // Adjust for shadow position (x, y) + ), + ]), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + // flex: 3, + child: Padding( + padding: const EdgeInsets.only(top: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText( + "Total Balance", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 8), + SizedBox( + width: 160, + child: AutoSizeText( + "${depositAccount.pcrCurrshort} ${depositAccount.mbmBkmsbalance.toStringAsFixed(2)}", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 20, fontWeight: FontWeight.w400), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + const SizedBox(width: 30), + Flexible( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [Image.asset(controller.getFlagWithCurrencyCode(depositAccount.pcrCurrcode), width: 30, height: 30)], + ), + ) + ], + )), + ))) + .toList(), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.toNamed(Routes.ADD_NEW_ACCOUNT); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 14.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 2), // Adjust for shadow position (x, y) + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 0), // Adjust for shadow position (x, y) + ), + ]), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 3, + child: Padding( + padding: const EdgeInsets.only(top: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textAddAccount), + style: context.textTheme.titleSmall!.copyWith(fontSize: 15, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + CustomText( + "40+ currencies", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + overflow: TextOverflow.ellipsis, + ) + ], + ), + ), + ), + const SizedBox(width: 30), + Flexible( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + // height: 50, + // width: 50, + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.circular(50.0), + ), + child: Image.asset(AppAssets.ic_add_new_Account, height: 15, width: 15), + ) + ], + ), + ) + ], + )), + ), + ], + ), + ), + const SizedBox(height: 10), + controller.depositeAccount.isNotEmpty + ? Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: controller.depositeAccount.length, + itemBuilder: (context, index) { + return depositAccountItem(controller, context, index); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 10)); + }, + ), + ), + ), + ) + : const Center( + child: Text("No deposit accounts found."), + ) + ], + ), + ), + ], + ); + }); + }); + } + + GestureDetector depositAccountItem(DashboardScreenController controller, BuildContext context, int index) { + return GestureDetector( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT, arguments: {"accountNumber": controller.depositeAccount.elementAt(index).mbmBkmsnumber}); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), + child: Container( + // padding: const EdgeInsets.all(5.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(0), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2.0, + blurRadius: 4.0, + offset: const Offset(0, 2), + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2.0, + blurRadius: 4.0, + offset: const Offset(0, 0), + ), + ]), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(width: 7), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Align(alignment: Alignment.bottomRight, child: Image.asset(controller.getFlagWithCurrencyCode(controller.depositeAccount.elementAt(index).pcrCurrcode), width: 40, height: 40, fit: BoxFit.cover)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: Column(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ + CustomText( + "${controller.depositeAccount.elementAt(index).mbmBkmstitle.toString()} (${controller.depositeAccount.elementAt(index).pcrCurrshort})", + style: Theme.of(Get.context!).textTheme.titleSmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + CustomText( + controller.depositeAccount.elementAt(index).mbmBkmsnumber.toString(), + style: Theme.of(Get.context!).textTheme.titleSmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w500), + ), + ]), + ), + Expanded( + flex: 3, + child: Align( + alignment: Alignment.centerRight, + child: CustomText( + "${controller.depositeAccount.elementAt(index).pcrCurrshort} ${controller.depositeAccount.elementAt(index).mbmBkmsbalance.toStringAsFixed(2)}", + style: context.textTheme.titleMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400), + ), + ), + ), + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, + child: Padding( + padding: const EdgeInsets.only(top: 26), + child: SizedBox( + height: 55, + width: 55, + child: SvgPicture.asset( + fit: BoxFit.cover, + AppAssets.ic_desposit_account_arrow, + height: 45, + width: 40, + )), + )), + ], + ), + ), + ), + ); + } +} + +class AddMoneyAndKyc extends StatelessWidget { + const AddMoneyAndKyc({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 22, right: 22), + child: Row( + children: [ + GestureDetector( + onTap: () { + Get.toNamed(Routes.ADD_MONEY); + }, + child: Container( + padding: const EdgeInsets.all(15.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + border: Border.all(color: AppColors.ff444444), + ), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + child: Row( + children: [ + CustomText( + "Add Money", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox( + width: 4, + ), + const Icon(Icons.add, color: Colors.green, size: 15) + ], + ), + ), + ), + ), + const Spacer(), + Container( + decoration: BoxDecoration( + color: SessionCache.instance.userInfo.isKycVerified ? Colors.green : AppColors.ffF95846, + borderRadius: const BorderRadius.only(topLeft: Radius.circular(22), bottomRight: Radius.circular(22)), + ), + padding: const EdgeInsets.only(top: 5.5, bottom: 5.5, left: 12, right: 12), + child: Row( + children: [ + CustomText( + SessionCache.instance.userInfo.isKycVerified ? "KYC verified" : "KYC Unverified", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 11, + color: Colors.white, + fontWeight: FontWeight.w400, + ), + ), + const SizedBox(width: 4), + SvgPicture.asset( + SessionCache.instance.userInfo.isKycVerified ? AppAssets.ic_tick_option : AppAssets.ic_cross_white, + width: 15, + height: 15, + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_binding.dart b/lib/app/modules/faqs/bindings/faqs_binding.dart new file mode 100644 index 0000000..75ffce8 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_controller.dart'; + +class FaqsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart new file mode 100644 index 0000000..fa3ad87 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_first_screen_controller.dart'; + +class FaqsFirstBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsFirstController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart new file mode 100644 index 0000000..ea0c0f8 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_second_screen_controller.dart'; + +class FaqsSecondBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsSecondController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart new file mode 100644 index 0000000..b527384 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_third_screen_controller.dart'; + +class FaqsThirdBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsThirdController(), + ); + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_controller.dart b/lib/app/modules/faqs/controllers/faqs_controller.dart new file mode 100644 index 0000000..ca4f151 --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_controller.dart @@ -0,0 +1,1218 @@ +import 'package:get/get.dart'; + +import '../views/model/FAQS.dart'; + +class FaqsController extends GetxController { + late FaqsModel faqsModel; + final searchText = ''.obs; + var filteredListSendingMoney = [].obs; + + @override + onInit() { + super.onInit(); + loadData(); + debounce(searchText, (_) => filterListSendingMoney(), time: const Duration(milliseconds: 300)); + } + + loadData() { + faqsModel = FaqsModel.fromMap(faqsJson); + filteredListSendingMoney.value = faqsModel.sendingMoney; + update(); + } + + void filterListSendingMoney() { + if (searchText.isEmpty) { + filteredListSendingMoney.value = faqsModel.sendingMoney; + } else { + filteredListSendingMoney.value = faqsModel.sendingMoney.where((item) => item.title.toLowerCase().contains(searchText.value.toLowerCase())).toList(); + } + } + + List get filteredSendingMoney { + if (searchText.value.isEmpty) { + return faqsModel.sendingMoney; + } else { + return faqsModel.sendingMoney.where((sendingMoney) => sendingMoney.title.toLowerCase().contains(searchText.value.toLowerCase()) || sendingMoney.description.toLowerCase().contains(searchText.value.toLowerCase()) || sendingMoney.questions.any((question) => question.title.toLowerCase().contains(searchText.value.toLowerCase()) || question.subQuestions.any((subQuestion) => subQuestion.title.toLowerCase().contains(searchText.value.toLowerCase()) || subQuestion.questionDetails.any((questionDetail) => questionDetail.question.toLowerCase().contains(searchText.value.toLowerCase()) || questionDetail.answer.toLowerCase().contains(searchText.value.toLowerCase()))))).toList(); + } + } +} + +/// Corrected JSON structure +var faqsJson = { + "Sending_money": [ + { + "title": "Sending money", + "description": "Setting up, paying for, editing, and cancelling transfers.", + "ImageProvider": "assets/uco/icons/ic_snding_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Can I sendexact amounts?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How do you notify meabout a transfer?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How do I download a transfer receipt?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Do I need to pay any tax on transfers?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How can I repeat a transfer?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Can I send from someone else's bank account?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Managing your account", + "description": "Setting up your account and getting verified.", + "ImageProvider": "assets/uco/icons/ic_manage_account.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Holding money", + "description": "Holding balances, setting up Direct Debits, and using \nInterest & Stocks.", + "ImageProvider": "assets/uco/icons/ic_holding_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Wise card", + "description": "Ordering, activating, spending, and troubleshooting.", + "ImageProvider": "assets/uco/icons/ic_wise_card.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Receiving money", + "description": "Using your account details to receive money.", + "ImageProvider": "assets/uco/icons/ic_receiving_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + ] +}; diff --git a/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart new file mode 100644 index 0000000..f3dffd2 --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart @@ -0,0 +1,27 @@ +import 'package:get/get.dart'; + +import '../views/model/FAQS.dart'; + +class FaqsFirstController extends GetxController { + late SendingMoney sendMoney; + final searchText = ''.obs; + RxList filteredListQuestions = [].obs; + @override + onInit() { + super.onInit(); + sendMoney = Get.arguments; + filteredListQuestions.value = sendMoney.questions; + debounce(searchText, (_) => filterListQuestions(), time: const Duration(milliseconds: 300)); + } + + void filterListQuestions() { + if (searchText.value.isEmpty) { + filteredListQuestions.value = sendMoney.questions; + } else { + filteredListQuestions.value = sendMoney.questions + .where((question) => + question.title.toLowerCase().contains(searchText.value.toLowerCase())) + .toList(); + } + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart new file mode 100644 index 0000000..b2c56df --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart @@ -0,0 +1,34 @@ +import 'package:get/get.dart'; + +import '../../../core/utils/logs_utils.dart'; +import '../views/model/FAQS.dart'; + + +class FaqsSecondController extends GetxController { + late Question question; + final searchText = ''.obs; + RxList filteredListSubQuestions = [].obs; + + @override + onInit() { + super.onInit(); + question = Get.arguments; + filteredListSubQuestions.value = question.subQuestions; + debounce(searchText, (_) => filterListQuestions(), time: const Duration(milliseconds: 300)); + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + dp("filteredListSubQuestions", filteredListSubQuestions.toString()); + } + + void filterListQuestions() { + if (searchText.value.isEmpty) { + filteredListSubQuestions.value = question.subQuestions; + } else { + filteredListSubQuestions.value = question.subQuestions.where((question) => question.title.toLowerCase().contains(searchText.value.toLowerCase())).toList(); + } + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart new file mode 100644 index 0000000..b74a04e --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/faqs/views/faqs_view.dart'; +import '../views/model/FAQS.dart'; + +class FaqsThirdController extends GetxController { + late SubQuestion subQuestion; + @override + onInit() { + super.onInit(); + subQuestion = Get.arguments; + } +} diff --git a/lib/app/modules/faqs/views/faqs_first_screen_view.dart b/lib/app/modules/faqs/views/faqs_first_screen_view.dart new file mode 100644 index 0000000..ede1339 --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_first_screen_view.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_first_screen_controller.dart'; + +class FaqsFirstScreenView extends GetView { + FaqsFirstScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var firstScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(firstScreenController.sendMoney.title, style: Theme + .of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(Icons.search, size: 15.0, color: Colors.grey[800]), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme + .of(context) + .textTheme + .bodySmall + ?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => firstScreenController.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: firstScreenController.filteredListQuestions.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_SECOND_SCREEN, arguments: firstScreenController.sendMoney.questions[index]); + }, + child: Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Row( + children: [ + Text( + firstScreenController.filteredListQuestions[index].title, + style: context.textTheme.bodySmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_second_screen_view.dart b/lib/app/modules/faqs/views/faqs_second_screen_view.dart new file mode 100644 index 0000000..c15b2ad --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_second_screen_view.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_second_screen_controller.dart'; + +class FaqsSecondScreenView extends GetView { + FaqsSecondScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var secondScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(secondScreenController.question.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => secondScreenController.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: secondScreenController.filteredListSubQuestions.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 15.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_THIRD_SCREEN, arguments: secondScreenController.question.subQuestions[index]); + }, + child: Row( + children: [ + Text( + secondScreenController.filteredListSubQuestions[index].title, + style: context.textTheme.bodySmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_third_screen_view.dart b/lib/app/modules/faqs/views/faqs_third_screen_view.dart new file mode 100644 index 0000000..bf7711b --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_third_screen_view.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_third_screen_controller.dart'; + +class FaqsThirdScreenView extends GetView { + FaqsThirdScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var thirdScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(thirdScreenController.subQuestion.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.answer, style: Theme.of(context).textTheme.bodySmall?.copyWith( fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text("How to send money with UCO", style: Theme.of(context).textTheme.titleSmall?.copyWith( fontSize: 18, fontWeight: FontWeight.w500, color: AppColors.black)), + const SizedBox(height: 20), + Expanded( + flex: 4, + child: ListView.builder( + itemCount: controller.faqsModel.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions?.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions![index].optionTitle, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 12, fontWeight: FontWeight.w700)), + const SizedBox(height: 10), + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions![index].optionAnswer, style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + ], + ); + },), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_view.dart b/lib/app/modules/faqs/views/faqs_view.dart new file mode 100644 index 0000000..61e68f2 --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_view.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; + +class FaqsView extends GetView { + FaqsView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textHowCanIHelpYou), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => controller.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExploreAllArticles), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Container( + height: 1, + width: double.infinity, + color: AppColors.colorGrey350, + ), + const SizedBox(height: 30), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: controller.filteredListSendingMoney.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_FIRST_SCREEN, arguments: faqs.sendingMoney[index]); + }, + child: Row( + children: [ + SvgPicture.asset(faqs.sendingMoney[index].imageProvider, height: 40), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + controller.filteredSendingMoney[index].title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + Text( + controller.filteredSendingMoney[index].description, + style: context.textTheme.bodySmall!.copyWith(fontSize: 9, fontWeight: FontWeight.w400), + ), + ], + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/model/FAQS.dart b/lib/app/modules/faqs/views/model/FAQS.dart new file mode 100644 index 0000000..b28d3ef --- /dev/null +++ b/lib/app/modules/faqs/views/model/FAQS.dart @@ -0,0 +1,187 @@ +class FaqsModel { + List sendingMoney; + + FaqsModel({required this.sendingMoney}); + + factory FaqsModel.fromMap(Map? map) { + return FaqsModel( + sendingMoney: List.from((map?['Sending_money'] ?? []).map((x) => SendingMoney.fromMap(x))), + ); + } + + Map toMap() { + return { + 'Sending_money': sendingMoney.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'FaqsModel{sendingMoney: $sendingMoney}'; + } +} + +class SendingMoney { + String title; + String description; + String imageProvider; + List questions; + + SendingMoney({ + required this.title, + required this.description, + required this.imageProvider, + required this.questions, + }); + + factory SendingMoney.fromMap(Map? map) { + return SendingMoney( + title: map?['title'] ?? "", + description: map?['description'] ?? "", + imageProvider: map?['ImageProvider'] ?? "", + questions: List.from((map?['questions'] ?? []).map((x) => Question.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'description': description, + 'ImageProvider': imageProvider, + 'questions': questions.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'SendingMoney{title: $title, description: $description, imageProvider: $imageProvider, questions: $questions}'; + } +} + +class Question { + String title; + List subQuestions; + + Question({ + required this.title, + required this.subQuestions, + }); + + factory Question.fromMap(Map? map) { + return Question( + title: map?['title'] ?? "", + subQuestions: List.from((map?['sub_questions'] ?? []).map((x) => SubQuestion.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'sub_questions': subQuestions.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'Question{title: $title, subQuestions: $subQuestions}'; + } +} + +class SubQuestion { + String title; + List questionDetails; + + SubQuestion({ + required this.title, + required this.questionDetails, + }); + + factory SubQuestion.fromMap(Map? map) { + return SubQuestion( + title: map?['title'] ?? "", + questionDetails: List.from((map?['questions_details'] ?? []).map((x) => QuestionDetails.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'questions_details': questionDetails.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'SubQuestion{title: $title, questionDetails: $questionDetails}'; + } +} + +class QuestionDetails { + String question; + String answer; + List multipleOptions; + String? builtPoint1; + String? builtPoint2; + + QuestionDetails({ + required this.question, + required this.answer, + required this.multipleOptions, + this.builtPoint1, + this.builtPoint2, + }); + + factory QuestionDetails.fromMap(Map? map) { + return QuestionDetails( + question: map?['question'] ?? "", + answer: map?['answer'] ?? "", + multipleOptions: List.from((map?['multiple_options'] ?? []).map((x) => MultipleOption.fromMap(x))), + builtPoint1: map?['built_point_1'], + builtPoint2: map?['built_point_2'], + ); + } + + Map toMap() { + return { + 'question': question, + 'answer': answer, + 'multiple_options': multipleOptions.map((x) => x.toMap()).toList(), + 'built_point_1': builtPoint1, + 'built_point_2': builtPoint2, + }; + } + + @override + String toString() { + return 'QuestionDetails{question: $question, answer: $answer, multipleOptions: $multipleOptions, builtPoint1: $builtPoint1, builtPoint2: $builtPoint2}'; + } +} + +class MultipleOption { + String optionTitle; + String optionAnswer; + + MultipleOption({ + required this.optionTitle, + required this.optionAnswer, + }); + + factory MultipleOption.fromMap(Map? map) { + return MultipleOption( + optionTitle: map?['option_title'] ?? "", + optionAnswer: map?['option_answer'] ?? "", + ); + } + + Map toMap() { + return { + 'option_title': optionTitle, + 'option_answer': optionAnswer, + }; + } + + @override + String toString() { + return 'MultipleOption{optionTitle: $optionTitle, optionAnswer: $optionAnswer}'; + } +} diff --git a/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart b/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart new file mode 100644 index 0000000..4566a0d --- /dev/null +++ b/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/general_ledger_controller.dart'; + +class GeneralLedgerBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => GeneralLedgerController(), + ); + } +} diff --git a/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart b/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart new file mode 100644 index 0000000..97950ec --- /dev/null +++ b/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../models/GlsResponseModel.dart'; +import '../../../models/evaluated_cuency_model.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; + +class GeneralLedgerController extends GetxController { + final AppRepositories repository = Get.find(); + late InputField messageField; + late InputField glsAccounts; + late InputField userTransactionPinField; + TextEditingController pinPutController = TextEditingController(); + + RxList allGlsAccounts = RxList.empty(); + Rx selectedGlAccount = Rx(null); + GLACCAddMoneyRequestModel transactionSubmitRequestModel = GLACCAddMoneyRequestModel.empty(); + Rx evaluatedCurrencyModel = EvaluatedCurrencyModel.empty().obs; + + @override + void onInit() { + super.onInit(); + + // var arguments = Get.arguments; + // + // transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? GLACCAddMoneyRequestModel.empty() : GLACCAddMoneyRequestModel.empty()); + // + // evaluatedCurrencyModel.value = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? EvaluatedCurrencyModel.empty() : EvaluatedCurrencyModel.empty()); + // + // fetchAllGlsAccounts(); + } + + @override + void dispose() { + pinPutController.clear(); + super.dispose(); + } + + void updateSelectedDeposit(DropDown item) { + // selectedGlAccount.value = item; + } + + clearAll() { + messageField.clear(); + glsAccounts.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + selectedGlAccount = Rx(null); + } + + Future fetchAllGlsAccounts() async { + ServerResponse response = await repository.fetchGlsAccounts(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + List list = List.from(((response.response ?? []) as List).map((x) => GlsResponseModel.fromMap(x)) ?? []); + SessionCache.instance.glsAccountsList.value = list; + allGlsAccounts.clear(); + for (int i = 0; i < list.length; i++) { + GlsResponseModel glsResponseModel = list.elementAt(i); + allGlsAccounts.add( + DropDown(i.toString(), "${glsResponseModel.pcaGlaccode} - ${glsResponseModel.pcaGlacdesc}", glsResponseModel), + ); + } + allGlsAccounts.refresh(); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, GeneralLedgerController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + // bool validate() { + // bool isValid = FieldValidation.validateAll([glsAccounts, userTransactionPinField]); + // return isValid; + // } + + Future handleNextClick() async { + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + // + // ServerResponse response = await repository.sendAddMoneyOtp(transactionPinRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + // + // GlsResponseModel responseModel = selectedGlAccount.value!.data as GlsResponseModel; + // transactionSubmitRequestModel.drPcaGlaccode = responseModel.pcaGlaccode; + // transactionSubmitRequestModel.drPcaGlacdesc = responseModel.pcaGlacdesc; + + Get.toNamed(Routes.OTP_ADD_MONEY, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: evaluatedCurrencyModel.value, + // } + ); + } +} diff --git a/lib/app/modules/general_ledger/views/general_ledger_view.dart b/lib/app/modules/general_ledger/views/general_ledger_view.dart new file mode 100644 index 0000000..2fa1e32 --- /dev/null +++ b/lib/app/modules/general_ledger/views/general_ledger_view.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/general_ledger_controller.dart'; + +class GeneralLedgerView extends GetView { + const GeneralLedgerView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transAddMoney), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + onPressed: () { + controller.handleNextClick(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + child: Column( + children: [ + // Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectYourGLSAccount), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20)), + Card( + color: AppColors.colorGrey50, + margin: const EdgeInsets.symmetric(horizontal: 2, vertical: 10), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(12), + decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10)) // Add border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Text(TranslationKeys.makeTranslation(TranslationKeys.textConformation), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20)), + // const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textTotalAmount), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCurrency), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + ], + ), + )), + + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(controller.evaluatedCurrencyModel.value.sgtGntramtfc.toString(), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(controller.evaluatedCurrencyModel.value.targetPerEratrateact.toString(), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(getFlagWithCurrencyCode(controller.evaluatedCurrencyModel.value.pcrCurrcode.toString()), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + ], + ), + )), + + // Expanded( + // flex: 2, + // child: Padding( + // padding: const EdgeInsets.only(left: 12.0, right: 12.0), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Text("sdd", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("sds", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("skks", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("sk", style: Theme.of(context).textTheme.bodySmall), + // ], + // ), + // )), + ], + ), + ], + )), + ), + controller.glsAccounts = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select GL Account", + textInputAction: TextInputAction.done, + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select GL account", + dropDownType: DropDownType.SPECIAL, + items: controller.allGlsAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + controller.transactionPinDialog(context, controller); + }, + ), + + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterMessage), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.handleNextClick(); + }, + ), + ], + ), + ), + ); + } + + String getFlagWithCurrencyCode(String currencyCode) { + int currencyCodeInt = int.tryParse(currencyCode) ?? 0; + + if (currencyCodeInt == 586) { + return "PKR"; + } else if (currencyCodeInt == 997) { + return "USD"; + } else if (currencyCodeInt == 978) { + return "EUR"; + } else { + return ""; + } + } +} diff --git a/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart b/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart new file mode 100644 index 0000000..b21e5f7 --- /dev/null +++ b/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/internal_transaction_controller.dart'; + +class InternalAccountTransBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => InternalAccountTransController(), + ); + } +} diff --git a/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart b/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart new file mode 100644 index 0000000..0f34b33 --- /dev/null +++ b/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../routes/app_pages.dart'; + + +class InternalAccountTransController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + //drop down + RxList allFromAccounts = RxList.empty(); + Rx selectedFromAccount = DepositAccount.empty().obs; + + RxList allToAccounts = RxList.empty(); + Rx selectedToAccount = DepositAccount.empty().obs; + ExchangeRate? selectedExchangeRate; + + TextEditingController referenceCodeController = TextEditingController(); + + // fields + late InputField fromAccountField; + late InputField toAccountField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + @override + void onInit() { + super.onInit(); + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + allFromAccounts.add(DropDown(depositAccount.mbmBkmsnumber, "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + } + } + + @override + Future onReady() async { + super.onReady(); + disposeAllResources(); + onFromAccountSelection(allFromAccounts.elementAt(0)); + fromAccountField.setText((allFromAccounts.first.label)); + } + + void onFromAccountSelection(DropDown value) { + if (value.id == selectedToAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + fromAccountField.setText(""); + selectedFromAccount.value = DepositAccount.empty(); + } else { + selectedFromAccount.value = value.data as DepositAccount; + } + } + + void onToAccountSelection(DropDown value) { + if (value.id == selectedFromAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + toAccountField.setText(""); + selectedToAccount.value = DepositAccount.empty(); + } else { + selectedToAccount.value = value.data as DepositAccount; + } + + if (selectedToAccount.value.mbmBkmsnumber.isEmpty) { + return; + } + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == selectedToAccount.value.pcrCurrcode) { + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void disposeAllResources() { + fromAccountField.clear(); + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + fromAccountField, + toAccountField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + /// Send Transaction function + Future sendTransaction() async { + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + // + // TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drMbmBkmsnumber: selectedFromAccount.value.mbmBkmsnumber, + // drMbmBkmstitle: selectedFromAccount.value.mbmBkmstitle, + // drPcrCurrcode: selectedFromAccount.value.pcrCurrcode, + // drPcrCurrdesc: selectedFromAccount.value.pcrCurrdesc, + // drPcrCurrshort: selectedFromAccount.value.pcrCurrshort, + // crMbmBkmsnumber: selectedToAccount.value.mbmBkmsnumber, + // crMbmBkmstitle: selectedToAccount.value.mbmBkmstitle, + // crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectedFromAccount.value.dmpProdcode, + // transType: "DR", + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + // otdTrancomment: messageField.getCustomText(), + // isOtpRequired: false, + // cmpRefcode: referenceCodeField.getCustomText(), + // ); + // + // dp("********************>>>>>>>>>>>>******************", transactionSubmitRequestModel); + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + // + // ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + Get.toNamed(Routes.INTERNAL_TRANSACTION_OPT); + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.INTERNAL_TRANSACTION_PIN_REQUEST: transactionPinRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + // }); + } + + void clearTransaction() { + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } +} diff --git a/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart b/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart new file mode 100644 index 0000000..5b643bb --- /dev/null +++ b/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart @@ -0,0 +1,402 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/internal_transaction_controller.dart'; + +class InternalAccountTransView extends GetView { + const InternalAccountTransView({Key? key, this.showAppBar = true}) : super(key: key); + + final bool showAppBar; + + @override + Widget build(BuildContext context) { + Get.put(InternalAccountTransController()); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Internal Transfer", + /*TranslationKeys.makeTranslation(TranslationKeys.textUSend),*/ + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.fromAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}fromAccountField"), + controller: FormFieldConstants.instance().getController("${className}fromAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allFromAccounts, + onItemSelected: (item) { + // controller.updateSelectedDeposit(item!); + controller.onFromAccountSelection(item!); + }, + ), + controller.toAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}toAccountField"), + controller: FormFieldConstants.instance().getController("${className}toAccountField"), + labelText: "Select To Account", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allFromAccounts, + onItemSelected: (item) { + //controller.updateSelectedDeposit(item!); + controller.onToAccountSelection(item!); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.clearTransaction(); + controller.disposeAllResources(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, InternalAccountTransController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, InternalAccountTransController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart b/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart new file mode 100644 index 0000000..7cb3ae3 --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/internal_transaction_otp_controller.dart'; + + +class InternalTransactionOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => InternalTransactionOtpController(), + ); + } +} diff --git a/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart b/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart new file mode 100644 index 0000000..8a0c000 --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + + +class InternalTransactionOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + TransactionPinRequestModel internalTransPinRequestModel = TransactionPinRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + late DepositAccount fromAccount; + late DepositAccount toAccount; + late List beneficiaryList; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + internalTransPinRequestModel = (arguments != null ? arguments[AppConstants.INTERNAL_TRANSACTION_PIN_REQUEST] ?? TransactionPinRequestModel.empty() : TransactionPinRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + // transactionSubmitRequestModel.pinType = "TRAN"; + // + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRate, + // } + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.sendTransactionStep1(internalTransPinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart b/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart new file mode 100644 index 0000000..d0d3add --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/internal_transaction_otp_controller.dart'; + +class InternalTransactionOtpView extends GetView { + const InternalTransactionOtpView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/login/bindings/login_screen_binding.dart b/lib/app/modules/login/bindings/login_screen_binding.dart new file mode 100644 index 0000000..6bc2f56 --- /dev/null +++ b/lib/app/modules/login/bindings/login_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/login_screen_controller.dart'; + +class LoginScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => LoginScreenController(), + ); + } +} diff --git a/lib/app/modules/login/controllers/login_screen_controller.dart b/lib/app/modules/login/controllers/login_screen_controller.dart new file mode 100644 index 0000000..c86c6c9 --- /dev/null +++ b/lib/app/modules/login/controllers/login_screen_controller.dart @@ -0,0 +1,135 @@ +import 'dart:convert'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/finger_print_info.dart'; +import '../../../routes/app_pages.dart'; +import '../../app_setting/controllers/app_setting_controller.dart'; + +class LoginScreenController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + late InputField userNameInputField; + late InputField passwordInputField; + bool loginUsingFingerPrint = false; + + @override + Future onReady() async { + super.onReady(); + + if (kDebugMode) { + /// Ciihive server + // userNameInputField.setText("duck@gmail.com"); + // passwordInputField.setText("Test@123"); + + /// Local server + // userNameInputField.setText("nabeelx64@gmail.com"); + // passwordInputField.setText("App@123"); + } + } + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + AppSettingController.isRTL.value = Get.locale!.languageCode == "ar" || Get.locale!.languageCode == "ur"; + AppSettingController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, AppSettingController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, AppSettingController.isRTL.value); + Get.forceAppUpdate(); + update(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([userNameInputField, passwordInputField]); + return isValid; + } + + void validateAndLogin() async { + + + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + if (!AppUtils.isPasswordValid(passwordInputField.getCustomText(), 8)) { + Toasty.error( + TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + return; + } + + AuthenticationRequest request = AuthenticationRequest( + email: userNameInputField.getCustomText(), + password: passwordInputField.getCustomText(), + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + isOtpRequired: false, + ); + + ServerResponse response = await repository.login(request); + dp("server response", response); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + Get.toNamed(Routes.O_T_P_SCREEN, + arguments: {AppConstants.SIGN_UP_FIRST_STEP_DATA: request}); + } + + void fingerPrintLogin() async { + String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + if (info.isEmpty) { + Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textInvalidFingerprint)); + AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + return; + } + + FingerPrintInfo fingerPrintInfo = FingerPrintInfo.fromMap(jsonDecode(info)); + + if (fingerPrintInfo.cmpUserId.isEmpty || fingerPrintInfo.cmpCustpassword.isEmpty) { + Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textInvalidFingerprint)); + + AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + + return; + } + + SessionCache.instance.fingerPrintController.authenticate((status) async { + if (status) { + AuthenticationRequest request = AuthenticationRequest( + email: fingerPrintInfo.cmpUserId, + password: fingerPrintInfo.cmpCustpassword, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + ); + + ServerResponse response = await repository.login(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.O_T_P_SCREEN, arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + 'loginUsingFingerPrint': loginUsingFingerPrint, + + }); + // showOtpInputDialog(context); + } + }, false); + } +} diff --git a/lib/app/modules/login/views/login_screen_view.dart b/lib/app/modules/login/views/login_screen_view.dart new file mode 100644 index 0000000..ebfe57f --- /dev/null +++ b/lib/app/modules/login/views/login_screen_view.dart @@ -0,0 +1,613 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/login/views/shared/login_widget.dart'; + +// import 'package:url_launcher/url_launcher.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/data_source_auth/remote_data_source/app_remote_data_source.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/login_screen_controller.dart'; + +class LoginScreenView extends GetView { + const LoginScreenView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + Get.lazyPut(() => AppRemoteDataSource()); + Get.lazyPut(() => AppRepositoriesImpl(remoteDataSource: Get.find())); + print("Width login ${MediaQuery.sizeOf(context).width} "); + + print("Height login ${MediaQuery.sizeOf(context).height} "); + + String className = runtimeType.toString().split('.').last; + return SafeArea( + child: Scaffold( + persistentFooterButtons: [ + BottomNavigationBar( + backgroundColor: AppColors.colorSecondary.withOpacity(0.1), + elevation: 0, + type: BottomNavigationBarType.fixed, + items: [ + // + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textFindUAgent), AppAssets.ic_security, () { + Toasty.success("Coming Soon....."); + // Get.toNamed(Routes.O_T_P_SCREEN); + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs( + context, + TranslationKeys.makeTranslation( + TranslationKeys.textQRPay), + AppAssets.ic_QR, + () { + Get.toNamed(Routes.qrViewScreen); + }, + context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textHelp), AppAssets.ic_client, () { + Get.toNamed(Routes.faqsViews); + // showModalBottomSheetWidget(Get.context!); + + // Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textContactUs), AppAssets.ic_contact_us, () { + showBottomSheet(context); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + ], + ), + ], + body: SingleChildScrollView( + child: Column( + children: [ + GestureDetector( + onTap: () { + showCurrencyDialog(context); + }, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.only(right: 8.0, left: 8.0), + child: Container( + decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), + height: 60, + width: 30, + child: Padding( + padding: const EdgeInsets.only(top: 28.0, left: 5, right: 5), + child: SvgPicture.asset(AppAssets.ic_arrow_down, height: 10, width: 10), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Image.asset(AppAssets.uc_logo, height: 56, width: 130, fit: BoxFit.cover), + ), + const SizedBox(height: 20), + controller.userNameInputField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + hintText: "enter email", + labelText: "Email", + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + keyboardType: TextInputType.emailAddress, + ), + controller.passwordInputField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + hintText: "enter password", + labelText: "Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + onSubmitted: (value) { + controller.validateAndLogin(); + }, + ), + // controller.userNameField = CustomInputFieldCustom( + // refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + // controller: FormFieldConstants.instance().getController("${className}userNameField"), + // labelText: "User Name", + // ), + // const SizedBox(height: 20), + // controller.passwordField = CustomInputFieldCustom( + // refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + // controller: FormFieldConstants.instance().getController("${className}passwordField"), + // labelText: "Password", + // requiredPasswordIcon: true, + // isPassword: true, + // ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndLogin(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 8), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + const SizedBox(height: 10), + GestureDetector( + onTap: () { + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP1); + }, + child: Text.rich( + TextSpan( + text: TranslationKeys.makeTranslation(TranslationKeys.textNotRegisterUser), // First part of the text + style: Theme.of(context).textTheme.bodySmall, + children: [ + const WidgetSpan( + child: SizedBox(width: 8.0), // Adjust the width as needed for the space + ), + TextSpan( + text: TranslationKeys.makeTranslation(TranslationKeys.textRegisterNow), + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorDialogBG, fontWeight: FontWeight.w400), + ), + ], + ), + ), + ), + const SizedBox(height: 30), + Obx(() { + return Visibility( + visible: SessionCache.instance.fingerPrintController.isFingerprintSupported.value && SessionCache.instance.fingerPrintController.isFingerPrintExistInDB.value, + child: Center( + child: SizedBox( + width: 65, + height: 65, + child: Material( + child: InkWell( + onTap: () { + controller.loginUsingFingerPrint = true; + controller.fingerPrintLogin(); + }, + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), // Set the border radius + ), + child: Container( + decoration: BoxDecoration(color: AppColors.colorGrey800.withOpacity(0.50), borderRadius: const BorderRadius.all(Radius.circular(100))), + child: const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Icon( + color: AppColors.colorButton, + Icons.fingerprint_sharp, + size: 35.0, + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + }), + // controller.dateField = CustomDateTimePicker( + // refKey: FormFieldConstants.instance() + // .getFormKey("${className}dateField"), + // controller: FormFieldConstants.instance() + // .getController("${className}dateField"), + // labelText: "picker", + // ), + // SizedBox(height: 10), + // controller.genderField = CustomDropDown( + // listData: [DropDown(id: "id1", label: "Label1"), DropDown(id: "id2", label: "Label2"), DropDown(id: "id3", label: "Label3")].obs, + // labelText: "Gender", + // isRequired: true, + // ), + ], + ), + ) + ], + ), + )), + ); + } + + void showModalBottomSheetWidget(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + showModalBottomSheet( + context: context, + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + builder: (BuildContext context) { + return responsiveWidget( + Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + //border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + padding: const EdgeInsets.only(top: 12), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset(AppAssets.ic_cross, height: 15, width: 15), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "${supportBottomSheetList[index].image}", + ), + const SizedBox(height: 20), + Center( + child: LabelText("${supportBottomSheetList[index].title}"), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ); + }, + ); + } + + /// Contact Us Bottom Sheet Widget + showBottomSheet(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + anchorPoint: Offset.zero, + builder: (BuildContext context) { + return responsiveWidget( + Container(height: 25,width: 30, color: Colors.red, child: Text("data"),clipBehavior: Clip.none,),); + }, + ); + + showModalBottomSheet( + context: context, + builder: (context) => + contactUsBottomSheet(context, supportBottomSheetList), + ); + + Get.bottomSheet( + contactUsBottomSheet(context, supportBottomSheetList), + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } + + Widget contactUsBottomSheet(BuildContext context, List supportBottomSheetList) { + return responsiveWidget( + Stack( + fit: StackFit.loose, + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 15, + width: 15, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + margin: const EdgeInsets.only(bottom: 20), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "${supportBottomSheetList[index].image}", + height: 50, + width: 50, + ), + const SizedBox(height: 20), + Center( + child: LabelText( + "${supportBottomSheetList[index].title}", + style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14), + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } + + void showCurrencyDialog(BuildContext loginScreenContext) { + showGeneralDialog( + context: loginScreenContext, + barrierDismissible: true, + transitionDuration: const Duration(milliseconds: 500), + barrierLabel: MaterialLocalizations.of(loginScreenContext).dialogLabel, + barrierColor: Colors.black.withOpacity(0.5), + pageBuilder: (context, _, __) { + return responsiveWidget( + Stack( + children: [ + Positioned( + top: 200, + right: 0, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.only(right: 5.0, left: 8.0), + child: Container( + decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), + height: 70, + width: 30, + child: Padding( + padding: const EdgeInsets.only(top: 28.0, left: 5, right: 5), + child: SvgPicture.asset( + AppAssets.ic_arrow_down, + height: 10, + width: 10, + ), + ), + ), + ), + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: ClipPath( + clipper: MultipleRoundedCurveClipper(), + child: Card( + elevation: 2.0, + child: ListView( + shrinkWrap: true, + children: [ + Image.asset( + AppAssets.uc_logo, + height: 55, + width: 130, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textUPrimary), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUCash), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUSave), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUChaChing), style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text("\$1,800.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$500.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$1288.06", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$120,000.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: 20, + ) + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + ), + ); + }, + transitionBuilder: (context, animation, secondaryAnimation, child) { + return SlideTransition( + position: CurvedAnimation( + parent: animation, + curve: Curves.easeOut, + ).drive(Tween( + begin: const Offset(0, -1.0), + end: Offset.zero, + )), + child: child, + ); + }, + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} diff --git a/lib/app/modules/login/views/shared/bottom_sheet_login.dart b/lib/app/modules/login/views/shared/bottom_sheet_login.dart new file mode 100644 index 0000000..bd81841 --- /dev/null +++ b/lib/app/modules/login/views/shared/bottom_sheet_login.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +class BottomSheetLogin { + String _description = ""; + String _icon = ""; + String billTypes = ""; + Function()? onTap; + + BottomSheetLogin({ + required String description, + required String icon, + required this.onTap, + this.billTypes = "", + }) { + _description = description; + _icon = icon; + this.billTypes = ""; + } + + String get description => _description; + + set description(String value) { + _description = value; + } + + String get icon => _icon; + + set icon(String value) { + _icon = value; + } + + static List options = [ + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/handIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/productIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/faqsIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/ic_supportIcon.png", + onTap: () { + Get.back(); + showBottomSheet(); + }), + ]; + + /// Support Bottom Sheet Widget + static showBottomSheet() { + List supportBottomSheetList = [ + SupportBottomSheet( + image: "assets/icons/email_icon.png", + title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: "assets/icons/phone_icon.png", + title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + onTap: () { + // launch("tel:21213123123"); + }), + ]; + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: EdgeInsets.symmetric(horizontal: 20), + child: Wrap( + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textLogin), + style: TextStyle( + color: AppColors.colorPrimary, + fontSize: 14, + fontWeight: FontWeight.w500), + ), + InkWell( + onTap: () { + Get.back(); + }, + child: SvgPicture.asset("assets/icons/ic_crossIcon.png")), + ], + ), + ), + Container( + padding: EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset("${supportBottomSheetList[index].image}"), + SizedBox(height: 20), + Center( + child: Text("Data"), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + isScrollControlled: true, + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} diff --git a/lib/app/modules/login/views/shared/expaanded_container.dart b/lib/app/modules/login/views/shared/expaanded_container.dart new file mode 100644 index 0000000..8f82785 --- /dev/null +++ b/lib/app/modules/login/views/shared/expaanded_container.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import '../../../../res/app_colors.dart'; + + +class ExpandedContainer extends StatelessWidget { + @override + Widget build(BuildContext context) { + return ClipPath( + clipper: MultipleRoundedCurveClipper(), + child: Container( + height: 200, + width: double.infinity, + color: AppColors.colorPrimaryLight, + child: Column( + children: [ + Text("data"), + Text("data"), + Text("data"), + Text("data"), + Text("data"), + Text("data"), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/login/views/shared/login_widget.dart b/lib/app/modules/login/views/shared/login_widget.dart new file mode 100644 index 0000000..2634a94 --- /dev/null +++ b/lib/app/modules/login/views/shared/login_widget.dart @@ -0,0 +1,116 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_label.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../res/app_dimensions.dart'; +import 'bottom_sheet_login.dart'; + +class LoginWidgets { + static Widget bottomTabs(BuildContext context, String text, String iconName, VoidCallback onPress, TextStyle textStyle) { + return SizedBox( + width: 95, + height: 75, + child: InkWell( + onTap: onPress, + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), // Set the border radius + ), + child: Container( + padding: const EdgeInsets.all(8), // Add padding as needed + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey.withOpacity(0), + ), // Set border color + borderRadius: BorderRadius.circular(8), // Set border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Image( + image: AssetImage(iconName), + width: 30, + height: 30, + ), + ), + const SizedBox(height: 3), + Expanded( + child: Center( + child: LabelText(text, style: textStyle), + ), + ), + ], + ), + ), + ), + ); + } + + static void showBottomSheet(BuildContext context, List options, Function onPress) { + + Get.bottomSheet( + isScrollControlled: true, + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorPrimary, width: 1), borderRadius: BorderRadius.only(topLeft: Radius.circular(AppDimensions.radiusCard), topRight: Radius.circular(AppDimensions.radiusCard))), + margin: EdgeInsets.only(left: AppDimensions.screenVerticalPadding, right: AppDimensions.screenVerticalPadding), + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogin), style: Theme.of(context).textTheme.titleSmall), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset("assets/icons/ic_crossIcon.png")), + ], + ), + ), + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorPrimary, width: 1), borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage(bottomSheetLogin.icon), + width: 50, + ), + const SizedBox(height: 20), + Center( + child: LabelText(bottomSheetLogin.description, labelColor: AppColors.colorTitle, fontSize: 18), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ), + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(AppDimensions.radiusCard), topRight: Radius.circular(AppDimensions.radiusCard))), + ); + } +} diff --git a/lib/app/modules/login/views/shared/top_dialog.dart b/lib/app/modules/login/views/shared/top_dialog.dart new file mode 100644 index 0000000..20127bd --- /dev/null +++ b/lib/app/modules/login/views/shared/top_dialog.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class TopDialog extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + insetPadding: EdgeInsets.zero, + child: Stack( + alignment: Alignment.topCenter, + children: [ + Container( + margin: EdgeInsets.only(top: 60), + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Top Dialog Content', + style: TextStyle(fontSize: 20), + ), + SizedBox(height: 20), + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Close'), + ), + ], + ), + ), + Positioned( + top: 0, + child: Container( + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Text( + 'Top Dialog', + style: TextStyle(fontSize: 24, color: Colors.white), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart b/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart new file mode 100644 index 0000000..d1fd48e --- /dev/null +++ b/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/o_t_p_screen_controller.dart'; + +class OTPScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => OTPScreenController(), + ); + } +} diff --git a/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart b/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart new file mode 100644 index 0000000..31ed42f --- /dev/null +++ b/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/LoginResponseModel.dart'; +import '../../../models/VerifyLoginOtpRequest.dart'; +import '../../../models/resend_ot_login_model.dart'; +import '../../../routes/app_pages.dart'; +import '../../user_profile/controllers/user_profile_controller.dart'; + + +class OTPScreenController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + TextEditingController pinPutController = TextEditingController(); + AuthenticationRequest firstStepData = AuthenticationRequest.empty(); + + RxBool isResend = false.obs; + bool loginUsingFingerPrint = false; + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? AuthenticationRequest.empty() : AuthenticationRequest.empty()); + loginUsingFingerPrint = arguments[1]; + pinPutController.text = ""; + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + VerifyLoginOtpRequest request = VerifyLoginOtpRequest( + email: firstStepData.email, + password: firstStepData.password, + obpPincode: pinPutController.text, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + ); + + ServerResponse response = await repository.validateLoginPin(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + LoginResponseModel model = LoginResponseModel.fromJson(response.response); + + SessionCache.instance.userInfo.name = model.name.toString(); + SessionCache.instance.userInfo.cmpCuststatus = model.cmpCuststatus.toString(); + SessionCache.instance.userInfo.plcLocalcode = RequestConstants.plcLocacode.toString(); + SessionCache.instance.userInfo.cmpCustlastlogin = model.cmpCustlastlogin.toString(); + SessionCache.instance.userInfo.cmpCustcode = model.cmpCustcode.toString(); + SessionCache.instance.userInfo.jwtToken = model.jwtToken.toString(); + SessionCache.instance.userInfo.cmpUserId = firstStepData.email; + SessionCache.instance.userInfo.cmpCustpassword = firstStepData.password; + SessionCache.instance.userInfo.channelCode = RequestConstants.channelCode; + SessionCache.instance.userInfo.porOrgacode = RequestConstants.porOrgacode; + SessionCache.instance.userInfo.pctCstycode = RequestConstants.pctCstycode; + SessionCache.instance.userInfo.isKycVerified = model.isKycVerified; + SessionCache.instance.userInfo.isTranPinSet = model.isTranPinSet; + UserProfileController.cmpCustImage.value = model.cmpCustImage; + + if (!SessionCache.instance.userInfo.isTranPinSet) { + Get.offAndToNamed(Routes.CREATE_TRANSACTION_PIN); + return; + } + Get.offAndToNamed(Routes.DASHBOARD_SCREEN, /*arguments: {'loginUsingFingerPrint': loginUsingFingerPrint}*/); + } + + ///uco/changeTransactionPin + void resenOtp() async { + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resentOtpLoginSignUp( + ResendOtpLoginModel( + userRole: 'USER', + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: firstStepData.email, + isOtpRequire: false, + phone: '', + pinType: 'C_TRANPIN', + username: firstStepData.email, + ), + ); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + // countdownController.setOnRestart( + // () {}, + // ); + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} + +String getTime(int totalSeconds) { + int minutes = totalSeconds ~/ 60; + int seconds = totalSeconds % 60; + return '$minutes : $seconds'; +} diff --git a/lib/app/modules/login_otp/views/o_t_p_screen_view.dart b/lib/app/modules/login_otp/views/o_t_p_screen_view.dart new file mode 100644 index 0000000..f2236b7 --- /dev/null +++ b/lib/app/modules/login_otp/views/o_t_p_screen_view.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/o_t_p_screen_controller.dart'; + +class OTPScreenView extends GetView { + const OTPScreenView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + // PinCodeTextField( + // autoDisposeControllers: false, + // keyboardType: TextInputType.number, + // controller: controller.pinPutController, + // showCursor: true, + // autoDismissKeyboard: false, + // enablePinAutofill: true, + // length: 6, + // appContext: context, + // mainAxisAlignment: MainAxisAlignment.center, + // cursorColor: Colors.black.withOpacity(0.8), + // obscureText: false, + // animationType: AnimationType.fade, + // pinTheme: PinTheme( + // selectedColor: AppColors.colorGrey350, + // /*Colors.black.withOpacity(0.6),*/ + // inactiveColor: AppColors.colorGrey350, + // /*Colors.black.withOpacity(0.6),*/ + // activeColor: AppColors.colorGrey350, + // fieldOuterPadding: const EdgeInsets.all(5), + // shape: PinCodeFieldShape.box, + // borderRadius: BorderRadius.circular(5), + // fieldHeight: 40, + // fieldWidth: 43, + // activeFillColor: Colors.white, + // ), + // animationDuration: const Duration(milliseconds: 100), + // backgroundColor: Colors.transparent, + // enableActiveFill: false, + // onCompleted: (v) {}, + // onChanged: (value) {}, + // beforeTextPaste: (text) { + // return true; + // }, + // ), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 20, width: 20), + const SizedBox(width: 5), + // TimerCountdown( + // spacerWidth: 5, + // enableDescriptions: false, + // format: CountDownTimerFormat.minutesSeconds, + // endTime: DateTime.now().add( + // const Duration(seconds: 8), + // ), + // onEnd: () { + // dp("Timer finished", ""); + // controller.updateResend(true); + // }, + // ), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/my_account/bindings/my_account_binding.dart b/lib/app/modules/my_account/bindings/my_account_binding.dart new file mode 100644 index 0000000..179ff62 --- /dev/null +++ b/lib/app/modules/my_account/bindings/my_account_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/my_account_controller.dart'; + +class MyAccountBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => MyAccountController(), + ); + } +} diff --git a/lib/app/modules/my_account/controllers/my_account_controller.dart b/lib/app/modules/my_account/controllers/my_account_controller.dart new file mode 100644 index 0000000..dc59180 --- /dev/null +++ b/lib/app/modules/my_account/controllers/my_account_controller.dart @@ -0,0 +1,84 @@ +import 'package:get/get.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/UserInfo.dart'; + + +class MyAccountController extends GetxController { + RxString fromAccountTitle = "".obs; + RxString fromAccountNumber = "".obs; + + RxInt selectedIndex = 0.obs; + RxString accountTitleText = "".obs; + RxString accountNumber = "".obs; + RxString accountIBNNumber = "".obs; + RxString branchCode = "".obs; + RxString accountOpeningDate = "".obs; + + /// show Selected indexBased String method + String getSelectedDisplayText() { + if (selectedIndex.value >= 0 && selectedIndex.value < dropdownItems.length) { + String fullText = dropdownItems[selectedIndex.value][0]; + return fullText.length > 20 ? fullText.substring(0, 20) + '...' : fullText; + } else { + return TranslationKeys.makeTranslation(TranslationKeys.textNoSelect); + } + } + + RxList totalAccount = RxList.empty(); + RxList dropdownItems = RxList.empty(); + RxList showAccountDetails = RxList.empty(); + UserInfo userInfo = UserInfo(); + + @override + void onInit() { + super.onInit(); + + DepositAccount selectAccount = DepositAccount(); + if (SessionCache.instance.depositAccountList.value.isNotEmpty) { + selectAccount = SessionCache.instance.depositAccountList.value[0]; + } + fromAccountTitle.value = selectAccount.mbmBkmstitle; + fromAccountNumber.value = selectAccount.mbmBkmsnumber; + accountTitleText.value = selectAccount.mbmBkmstitle; + accountNumber.value = selectAccount.mbmBkmsnumber; + //branchCode.value = selectAccount.plcLocadesc; + accountOpeningDate.value = selectAccount.mbmBkmsopendate; + + /// For Deposit Account List + for (int i = 0; i < SessionCache.instance.depositAccountList.value.length; i++) { + totalAccount.add(SessionCache.instance.depositAccountList.value[i].mbmBkmsnumber); + } + + /// For Loan Account List + // for (int i = 0; i < SessionCache.instance.loanAccountList.value.length; i++) { + // totalAccount.add(SessionCache.instance.loanAccountList.value[i].mbmBkmsnumber); + // } + + /// Assign to DropDown Items List + dropdownItems.assignAll(totalAccount); + print("The Total accounts lenght is ================== ${totalAccount}"); + + // for (int i = 0; i < SessionCache.instance.loanAccountList.value.length; i++) { + // showAccountDetails.add(SessionCache.instance.loanAccountList.value[i].mbmBkmstitle); + // showAccountDetails.add(SessionCache.instance.loanAccountList.value[i].plcLocadesc); + // } + for (int i = 0; i < SessionCache.instance.depositAccountList.value.length; i++) { + showAccountDetails.add(SessionCache.instance.depositAccountList.value[i].mbmBkmstitle); + //showAccountDetails.add(SessionCache.instance.depositAccountList.value[i].plcLocadesc); + } + } + + void setAccountDetails() { + accountTitleText.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmstitle; + accountNumber.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmsnumber; + accountIBNNumber.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmsnumber; + //branchCode.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].plcLocadesc; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmstitle; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmsnumber; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmsnumber; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].plcLocadesc; + } +} diff --git a/lib/app/modules/my_account/views/my_account_view.dart b/lib/app/modules/my_account/views/my_account_view.dart new file mode 100644 index 0000000..1ab99c7 --- /dev/null +++ b/lib/app/modules/my_account/views/my_account_view.dart @@ -0,0 +1,301 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +// import 'package:share_plus/share_plus.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/bottom_sheet.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../res/app_colors.dart'; +import '../../app_setting/controllers/app_setting_controller.dart'; +import '../controllers/my_account_controller.dart'; + +class MyAccountView extends GetView { + const MyAccountView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: + TranslationKeys.makeTranslation(TranslationKeys.textMyAccountTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx( + () { + return SingleChildScrollView( + child: Stack( + children: [ + Container( + height: 150, + decoration: BoxDecoration( + color: + AppColors.colorButton.withOpacity(0.98), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(40)))), + Column( + children: [ + InkWell( + onTap: () { + showBottomSheet(context, controller); + }, + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + margin: const EdgeInsets.only( + left: 10, right: 10, top: 15, bottom: 10), + color: Colors.white, + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColors.colorPrimary, + border: Border.all(color: AppColors.white), + borderRadius: BorderRadius.circular(15.0)), + child: ListTile( + title: Text(controller.fromAccountTitle.value, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.white)), + subtitle: Padding( + padding: const EdgeInsets.only(top: 5.0), + child: Text(controller.fromAccountNumber.value, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.white)), + ), + trailing: const Icon( + Icons.keyboard_arrow_down_sharp, + color: AppColors.white, + ), + ), + ), + ), + ), + const SizedBox( + height: 10, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + ), + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + elevation: 5.0, + child: Stack( + children: [ + GestureDetector( + onTap: () { + String message = + 'Account Title: ${controller.accountTitleText.value}\nAccount Number: ${controller.accountNumber.value}\nBranch Code: ${controller.branchCode.value}'; + String subject = 'Subject for sharing'; + // Share.share(message, subject: subject); + }, + child: Align( + alignment: AppSettingController.isRTL.value + ? Alignment.topLeft + : Alignment.topRight, + child: const Padding( + padding: EdgeInsets.all(10.0), + child: CircleAvatar( + maxRadius: 10, + minRadius: 10, + backgroundColor: AppColors.transparent, + child: Icon(Icons.share, + size: 15, color: AppColors.colorPrimary), + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountTitle), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ), + const SizedBox(height: 5), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, bottom: 10), + child: Text( + controller.accountTitleText.value, + style: + Theme.of(context).textTheme.titleSmall, + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountNumber), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ), + Row( + children: [ + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + controller.accountNumber.value, + style: Theme.of(context) + .textTheme + .titleSmall, + ), + ), + const SizedBox(width: 20), + ], + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountBranchCode), + style: Theme.of(context) + .textTheme + .bodyMedium), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, + right: 15.0, + top: 10, + bottom: 10), + child: Text(controller.branchCode.value, + style: Theme.of(context) + .textTheme + .titleSmall), + ), + ], + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, vertical: 15.0), + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + elevation: 5.0, + child: SizedBox( + height: 60, + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15.0, right: 15), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountOpeningDate), + style: + Theme.of(context).textTheme.bodyMedium), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Text(controller.accountOpeningDate.value, + style: + Theme.of(context).textTheme.titleSmall), + ) + ], + ), + ), + ), + ), + ], + ), + ], + ), + ); + }, + ), + ); + } + + static void showBottomSheet( + BuildContext context, MyAccountController controller) { + List options = []; + for (int i = 0; + i < SessionCache.instance.depositAccountList.value.length; + i++) { + DepositAccount depositAccount = + SessionCache.instance.depositAccountList.value[i]; + options.add(OptionData.withData(depositAccount.mbmBkmstitle, + depositAccount.mbmBkmsnumber, depositAccount)); + } + // for (int i = 0; i < SessionCache.instance.loanAccountList.length; i++) { + // LoanAccount loanAccount = SessionCache.instance.loanAccountList[i]; + // options.add(OptionData.withData( + // loanAccount.mbmBkmstitle, loanAccount.mbmBkmsnumber, loanAccount)); + // } + + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey800, width: 1), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, (selectedOption) { + if (selectedOption.dataObject is DepositAccount) { + DepositAccount selectAccount = + selectedOption.dataObject as DepositAccount; + controller.fromAccountTitle.value = selectAccount.mbmBkmstitle; + controller.fromAccountNumber.value = selectAccount.mbmBkmsnumber; + controller.accountTitleText.value = selectAccount.mbmBkmstitle; + controller.accountNumber.value = selectAccount.mbmBkmsnumber; + // controller.branchCode.value = selectAccount.plcLocadesc; + controller.accountOpeningDate.value = selectAccount.mbmBkmsopendate; + } + // if (selectedOption.dataObject is LoanAccount) { + // LoanAccount selectAccount = + // selectedOption.dataObject as LoanAccount; + // controller.fromAccountTitle.value = selectAccount.mbmBkmstitle; + // controller.fromAccountNumber.value = selectAccount.mbmBkmsnumber; + // controller.accountTitleText.value = selectAccount.mbmBkmstitle; + // controller.accountNumber.value = selectAccount.mbmBkmsnumber; + // controller.branchCode.value = selectAccount.plcLocadesc; + // controller.accountOpeningDate.value = selectAccount.mbmBkmsopendate; + // } + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} diff --git a/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart b/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart new file mode 100644 index 0000000..6692c31 --- /dev/null +++ b/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/new_beneficiary_controller.dart'; + +class NewBeneficiaryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NewBeneficiaryController(), + ); + } +} diff --git a/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart b/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart new file mode 100644 index 0000000..1693b4f --- /dev/null +++ b/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart @@ -0,0 +1,270 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +// import 'package:flutter_contacts/flutter_contacts.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AccountInquiryResponseModel.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; + +class NewBeneficiaryController extends GetxController { + String OPTION_PHONE = "01"; + String OPTION_EMAIL = "02"; + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + RxList allRecipientDetailOptions = RxList.empty(); + Rx selectedRecipientDetailOption = DropDown.empty().obs; + + String className = ""; + late InputField selectRecipientDetailField; + late InputField identityPhoneNumberField; + late InputField identityEmailField; + late InputField recipientCardNameField; + late InputField accountNumberField; + late InputField nickNameField; + + // late InputField emailIDField; + // late InputField phoneNumberField; + + String receiverAccountNumber = ""; + String receiverAccountTitle = ""; + RxString currencySymbol = "".obs; + // Contact? selectedContact; + ExchangeRate? selectedExchangeRate; + + @override + void onInit() { + super.onInit(); + allRecipientDetailOptions.value = [ + DropDown(OPTION_PHONE, TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber)), + DropDown(OPTION_EMAIL, TranslationKeys.makeTranslation(TranslationKeys.textEmail)), + ]; + } + + /// Validate Method + bool validate() { + bool isValid = FieldValidation.validateAll([ + // accountTitleField, + // accountNumberField, + nickNameField, + selectRecipientDetailField + // identityEmailField, + // accountNumberField, + // emailIDField, + // phoneNumberField, + ]); + + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + return isValid; + } + + /// Request Method + Future addToNewBeneficiary({navigate = true}) async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + // BeneficiaryAccountModel beneficiaryAccountModel = BeneficiaryAccountModel( + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // pcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // pcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // mbmBkmstitleRef: receiverAccountTitle, + // mbmBkmsnumberRef: receiverAccountNumber, + // refPhoneNumber: "", + // refEmail: "", + // refNickName: nickNameField.getCustomText(), + // ); + // ServerResponse response = await repository.addNewBeneficiary(beneficiaryAccountModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + CustomDialog.showSuccessDialog( + description: "You are successfully add new Beneficiary", + onTapPositive: () { + Get.back(result: true); + }); + clearNewBeneficiaryControllers(); + } + + void updateRecipientDetail(DropDown? item) { + selectedRecipientDetailOption.value = item!; + } + + Future selectContact() async { + dynamic result = await Get.toNamed(Routes.CONTACTS_SCREEN); + + // if ((result != null && result[AppConstants.SELECTED_CONTACT] != null)) { + // selectedContact = result[AppConstants.SELECTED_CONTACT]; + // identityPhoneNumberField.setText(AppUtils.formatPhoneNumber(selectedContact!.phones.first.number) /*"${selectedContact!.displayName} (${AppUtils.formatPhoneNumber(selectedContact!.phones.first.number + ")")}"*/); + // } + } + + // void scanQr() async { + // Get.put(QrSettingController()); + // var scanResult = await Get.to(() => const QrScanScreen()); + // var resultJson = jsonDecode(scanResult); + // var accNumber = resultJson["phoneNumber"]; + // identityPhoneNumberField.setText(accNumber); + // verifyAccountAgainstIt(); + // } + + Future verifyAccountAgainstIt() async { + String valua = selectedRecipientDetailOption.value.id == OPTION_PHONE ? identityPhoneNumberField.getCustomText() : (selectedRecipientDetailOption.value.id == OPTION_EMAIL ? identityEmailField.getCustomText() : ""); + bool isValid = true; + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + if (!isValid) { + Toasty.error("Please input and then proceed"); + return; + } + + ServerResponse response = await repository.fetchAccountInquiry(selectedRecipientDetailOption.value.id, valua); + + if (response.isError) { + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + identityPhoneNumberField.setError(response.errorMsg); + } else { + identityEmailField.setError(response.errorMsg); + } + return; + } + List responseData = response.response ?? []; + List accountInquiryList; + accountInquiryList = AccountInquiryResponseModel.fromList(responseData); + + accountsDialog(accountInquiryList); + // AccountInquiryResponseModel transactionSubmitRequestModel = AccountInquiryResponseModel.fromMap(((response.response ?? {}) as Map).map((key, value) => MapEntry(key.toString(), value))); + } + + void updateSelectedCurrency(/*DropDown? item*/ AccountInquiryResponseModel model) { + print("************************model>> $model"); + + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + print("************************elementAt(i).pcrCurrcode>> ${SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode}"); + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == model.pcrCurrcode) { + currencySymbol.value = SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrshort; + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + // exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void accountsDialog(List accountInquiryList) { + if (accountInquiryList.length == 1) { + receiverAccountTitle = accountInquiryList.first.mbmBkmstitle; + receiverAccountNumber = accountInquiryList.first.mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList.first); + return; + } + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + ListView.separated( + shrinkWrap: true, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + receiverAccountTitle = accountInquiryList[index].mbmBkmstitle; + receiverAccountNumber = accountInquiryList[index].mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList[index]); + Get.back(); + }, + child: Column(children: [ + Container( + height: 40, + width: double.infinity, + decoration: const BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("${accountInquiryList[index].mbmBkmstitle} (${accountInquiryList[index].pcrCurrshort})", style: Theme.of(context).textTheme.titleSmall), + Text(accountInquiryList[index].mbmBkmsnumber, style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + ), + ]), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 5)); + }, + itemCount: accountInquiryList.length), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Clear Controllers Method + void clearNewBeneficiaryControllers() { + // accountTitleField.clear(); + nickNameField.clear(); + selectRecipientDetailField.clear(); + identityPhoneNumberField.clear(); + recipientCardNameField.clear(); + identityEmailField.clear(); + // accountNumberField.clear(); + // emailIDField.clear(); + // phoneNumberField.clear(); + } +} diff --git a/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart b/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart new file mode 100644 index 0000000..df4b97a --- /dev/null +++ b/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart @@ -0,0 +1,238 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/new_beneficiary_controller.dart'; + +class NewBeneficiaryView extends GetView { + const NewBeneficiaryView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "New Beneficiary", + onBackButtonPressed: () { + Get.back(); + controller.clearNewBeneficiaryControllers(); + }, + ) + : null, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + controller.addToNewBeneficiary(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textAddToBeneficiary), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + icon: const Icon(Icons.add, size: 18), + iconPadding: const EdgeInsets.only(right: 10.0), + ), + ), + ), + ], + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Obx(() { + return Column( + children: [ + // controller.accountTitleField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}accountTitleField"), + // controller: FormFieldConstants.instance().getController("${className}accountTitleField"), + // labelText: "Account Title", + // hintText: "Enter your account name", + // ), + // controller.accountNumberField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}accountNumberField"), + // controller: FormFieldConstants.instance().getController("${className}accountNumberField"), + // labelText: "Account Number", + // hintText: "Enter your account number", + // ), + controller.selectRecipientDetailField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectRecipientDetailField"), + controller: FormFieldConstants.instance().getController("${className}selectRecipientDetailField"), + labelText: "Recipient Detail", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allRecipientDetailOptions, + onItemSelected: (item) { + controller.updateRecipientDetail(item); + }, + ), + Column( + children: [ + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_PHONE, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityPhoneNumberField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + keyboardType: TextInputType.phone, + refKey: FormFieldConstants.instance().getFormKey("${className}identityPhoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityPhoneNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber), + hintText: "Select phone number", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + suffixIcon: SizedBox( + width: 70, + child: Row( + children: [ + GestureDetector( + onTap: () { + // controller.scanQr(); + }, + child: const Icon(Icons.qr_code, size: 25, color: AppColors.colorPrimary)), + const SizedBox( + width: 8, + ), + InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + onTap: () { + controller.selectContact(); + }, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: SvgPicture.asset(AppAssets.ic_select_contact, height: 25, width: 25), + ), + ), + ], + ), + ), + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_EMAIL, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityEmailField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + keyboardType: TextInputType.emailAddress, + refKey: FormFieldConstants.instance().getFormKey("${className}identityEmailField"), + controller: FormFieldConstants.instance().getController("${className}identityEmailField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + hintText: "Enter your email", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + ], + ), + controller.recipientCardNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}recipientCardNameField"), + controller: FormFieldConstants.instance().getController("${className}recipientCardNameField"), + labelText: TranslationKeys.makeTranslation("Account Title"), + hintText: "Account title", + readOnly: true, + showCursor: false, + ), + controller.nickNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}nickNameField"), + controller: FormFieldConstants.instance().getController("${className}nickNameField"), + labelText: "Nick Name", + hintText: "Enter your nick name", + ), + // controller.emailIDField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}emailIDField"), + // controller: FormFieldConstants.instance().getController("${className}emailIDField"), + // labelText: "Email ID", + // hintText: "Enter your email id", + // ), + // controller.phoneNumberField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}phoneNumberField"), + // controller: FormFieldConstants.instance().getController("${className}phoneNumberField"), + // labelText: "Phone Number", + // keyboardType: TextInputType.number, + // hintText: "Enter your phone number", + // ), + ], + ); + }), + ), + ), + ); + } +} diff --git a/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart b/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart new file mode 100644 index 0000000..40ba4a0 --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/new_beneficiary_otp_controller.dart'; + + +class NewBeneficiaryOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NewBeneficiaryOtpController(), + ); + } +} diff --git a/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart b/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart new file mode 100644 index 0000000..cb73a0b --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../routes/app_pages.dart'; + +class NewBeneficiaryOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + // var arguments = Get.arguments; + // transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + // exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + // + + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + transactionSubmitRequestModel.pinType = "TRAN"; + + transactionSubmitRequestModel.obpPincode = pinPutController.text; + + CustomDialog.showSuccessDialog( + description: "You have successfully added the Beneficiary.", + onTapPositive: () { + Get.offAndToNamed(Routes.BENEFICIARY_MANAGEMENT); + }, + title: "Beneficiary Added"); + } + + void resenOtp() async { + // + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resendOtpUsend(ResendOtpUsendModel( + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: SessionCache.instance.userInfo.cmpUserId, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequired: false, + pctCstycode: SessionCache.instance.userInfo.pctCstycode, + pinType: 'C_TRANPIN', + )); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart b/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart new file mode 100644 index 0000000..21ce47e --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; +import '../controllers/new_beneficiary_otp_controller.dart'; + +class NewBeneficiaryOtpView extends GetView { + const NewBeneficiaryOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.find().sendTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/notifications/bindings/notifications_binding.dart b/lib/app/modules/notifications/bindings/notifications_binding.dart new file mode 100644 index 0000000..33ccb22 --- /dev/null +++ b/lib/app/modules/notifications/bindings/notifications_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/notifications_controller.dart'; + +class NotificationsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NotificationsController(), + ); + } +} diff --git a/lib/app/modules/notifications/controllers/notifications_controller.dart b/lib/app/modules/notifications/controllers/notifications_controller.dart new file mode 100644 index 0000000..5b69a03 --- /dev/null +++ b/lib/app/modules/notifications/controllers/notifications_controller.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/date_picker.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../models/DepositAccountResponse.dart'; + +class NotificationsController extends GetxController { + RxString selectedAccountNumber = '123456789'.obs; + RxBool isExpanded = false.obs; + bool isCredit = false; + + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + List accountNumberList = ["123456789"]; + + List notificationList = [ + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + ]; + + late InputField depositAccountField; + + @override + void onInit() { + // + + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = + // SessionCache.instance.depositAccountList.elementAt(i); + // + // allDepositAccounts.add( + // DropDown( + // i.toString(), + // "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", + // depositAccount), + // ); + // } + + // selectedDepositAccount.value = allDepositAccounts.first.data; + + super.onInit(); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + } + + void showDialogFunction(BuildContext context) { + CustomDialog.showInfoDialog( + title: TranslationKeys.makeTranslation( + TranslationKeys.textNotificationDetails), + description: TranslationKeys.makeTranslation( + TranslationKeys.textNotificationDetailsContent), + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + }); + } + + void showDateRangePicker() async { + var date = await DatePicker.showRangeDatePicker(); + dp("Date is ", date); + } +} + +class NotificationDetails { + String description; + String dateTime; + + NotificationDetails({required this.description, required this.dateTime}); +} diff --git a/lib/app/modules/notifications/views/notifications_view.dart b/lib/app/modules/notifications/views/notifications_view.dart new file mode 100644 index 0000000..821a1ce --- /dev/null +++ b/lib/app/modules/notifications/views/notifications_view.dart @@ -0,0 +1,315 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../controllers/notifications_controller.dart'; + +class NotificationsView extends GetView { + const NotificationsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: + TranslationKeys.makeTranslation(TranslationKeys.textNotifications), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + height: 25, + decoration: const BoxDecoration( + color: AppColors.colorPrimary, + )), + GestureDetector( + onTap: () { + controller.showDateRangePicker(); + }, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + elevation: 5.0, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + //mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textFilter), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + ), + Image.asset( + AppAssets.ic_sort, + height: 25, + ), + const SizedBox( + width: 10, + ) + ], + ), + ), + ), + ), + ), + ], + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + // child: Align( + // alignment: Alignment.centerLeft, + // child: Text( + // TranslationKeys.makeTranslation( + // TranslationKeys.textPleaseSelectAccount), + // style: Theme.of(context) + // .textTheme + // .titleSmall + // ?.copyWith(color: AppColors.titleColor)), + // ), + // ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance() + .getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isTopMarginRequired: false, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + // child: SizedBox( + // height: 35, + // child: InkWell( + // onTap: () {}, + // child: DropdownButtonHideUnderline( + // child: ButtonTheme( + // alignedDropdown: true, + // child: DropdownButton2( + // isExpanded: true, + // hint: Row( + // mainAxisAlignment: MainAxisAlignment.spaceAround, + // children: [ + // const Icon( + // Icons.list, + // size: 20, + // color: Colors.yellow, + // ), + // const SizedBox( + // width: 4, + // ), + // Text(controller.selectedAccountNumber.value), + // ], + // ), + // items: controller.accountNumberList + // .toSet() + // .map((String item) => DropdownMenuItem( + // value: item, + // child: Text( + // item, + // style: Theme.of(context) + // .textTheme + // .bodyMedium + // ?.copyWith( + // fontSize: 12, + // fontWeight: FontWeight.w400, + // color: AppColors.colorText), + // overflow: TextOverflow.ellipsis, + // ), + // )) + // .toList(), + // value: controller.selectedAccountNumber.value, + // onChanged: (String? newValue) { + // if (newValue != null) { + // controller.selectedAccountNumber.value = newValue; + // } + // }, + // buttonStyleData: ButtonStyleData( + // height: 41, + // padding: const EdgeInsets.symmetric( + // horizontal: 10, vertical: 5), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(50), + // border: Border.all( + // color: AppColors.colorGrey350, + // ), + // color: AppColors.colorSecondary, + // ), + // elevation: 0, + // ), + // iconStyleData: IconStyleData( + // icon: SvgPicture.asset( + // AppAssets.ic_arrow_down, + // height: 15, + // width: 15, + // ), + // iconEnabledColor: AppColors.colorText, + // iconDisabledColor: AppColors.colorText, + // ), + // dropdownStyleData: DropdownStyleData( + // maxHeight: 150, + // width: 320, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(7), + // color: AppColors.colorSecondary, + // ), + // offset: const Offset(-2, 0), + // scrollbarTheme: ScrollbarThemeData( + // radius: const Radius.circular(40), + // thickness: MaterialStateProperty.all(5), + // thumbVisibility: + // MaterialStateProperty.all(true), + // ), + // ), + // menuItemStyleData: const MenuItemStyleData( + // height: 30, + // padding: EdgeInsets.only(left: 14, right: 14), + // ), + // ), + // ), + // ), + // ), + // ), + // ), + Expanded( + flex: 4, + child: controller.notificationList.isEmpty + ? const Center( + child: Text("No notifications are found"), + ) + : ListView.builder( + itemCount: controller.notificationList.length, + itemBuilder: (context, index) { + return InkWell( + onTap: () { + controller.showDialogFunction(context); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 0), + child: Card( + elevation: 2.0, + color: AppColors.white, + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + children: [ + Row( + children: [ + Text( + controller + .notificationList[0].description, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontSize: 10, + fontWeight: FontWeight.w400), + ) + ], + ), + const SizedBox(height: 5), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + controller + .notificationList[0].dateTime, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontSize: 10, + fontWeight: FontWeight.w400), + ), + ), + //const Expanded(child: SizedBox()), + Expanded( + child: Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Container( + height: 13, + width: 0.5, + color: AppColors.colorGrey800, + ), + const SizedBox( + width: 10, + ), + Text( + "Read more", + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + color: AppColors + .colorPrimary, + fontSize: 10, + fontWeight: + FontWeight.w400), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/password_change/bindings/password_change_binding.dart b/lib/app/modules/password_change/bindings/password_change_binding.dart new file mode 100644 index 0000000..ebea3a3 --- /dev/null +++ b/lib/app/modules/password_change/bindings/password_change_binding.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/password_change/controllers/password_change_controller.dart'; + +class ChangePasswordBindings extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangePasswordController(), + ); + } +} diff --git a/lib/app/modules/password_change/controllers/password_change_controller.dart b/lib/app/modules/password_change/controllers/password_change_controller.dart new file mode 100644 index 0000000..73898b6 --- /dev/null +++ b/lib/app/modules/password_change/controllers/password_change_controller.dart @@ -0,0 +1,79 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/models/chanange_password_params.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; + +class ChangePasswordController extends GetxController { + final AppRepositories repository = Get.find(); + late InputField oldPasswordField; + late InputField newPasswordField; + late InputField confirmNewPasswordField; + + bool validate() { + bool isValid = FieldValidation.validateAll([oldPasswordField, newPasswordField, confirmNewPasswordField]); + return isValid; + } + + changePassword() async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + bool otherValidation = true; + if (!AppUtils.isPasswordValid(oldPasswordField.getCustomText(), 8)) { + oldPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(newPasswordField.getCustomText(), 8)) { + newPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(confirmNewPasswordField.getCustomText(), 8)) { + confirmNewPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!otherValidation) { + return; + } + + if (newPasswordField.getCustomText() != confirmNewPasswordField.getCustomText()) { + Toasty.error("Passwords didn't match"); + return; + } + + // ServerResponse response = await repository.changePassword( + // ChangePasswordParams( + // newPassword: newPasswordField.getCustomText(), + // oldPassword: oldPasswordField.getCustomText(), + // email: SessionCache.instance.userInfo.cmpUserId, + // ), + // ); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + CustomDialog.showSuccessDialog( + // title: "Change Password", + description: " Password has been changed successfully", + onTapPositive: () { + clearFields(); + Get.back(); + }); + } + + void clearFields() { + oldPasswordField.clear(); + newPasswordField.clear(); + confirmNewPasswordField.clear(); + } +} diff --git a/lib/app/modules/password_change/views/password_change_view.dart b/lib/app/modules/password_change/views/password_change_view.dart new file mode 100644 index 0000000..55fd781 --- /dev/null +++ b/lib/app/modules/password_change/views/password_change_view.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/modules/password_change/controllers/password_change_controller.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; + +class ChangePasswordScreen extends GetView { + const ChangePasswordScreen({super.key}); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.changepassword), + onBackButtonPressed: () { + Get.back(); + controller.clearFields(); + }, + ), + body: GetBuilder(builder: (controller) { + return Padding( + padding: const EdgeInsets.only(right: 12.0, left: 12.0), + child: Column( + children: [ + const SizedBox(height: 20), + controller.oldPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}oldPassword"), + controller: FormFieldConstants.instance().getController("${className}oldPassword"), + hintText: "Enter old password", + labelText: "Old Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.newPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}newPassword"), + controller: FormFieldConstants.instance().getController("${className}newPassword"), + hintText: "Enter new password", + labelText: "New Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.confirmNewPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}confirmNewPasswordField"), + controller: FormFieldConstants.instance().getController("${className}confirmNewPasswordField"), + hintText: "Enter new password again", + labelText: "Confirm New Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ) + ], + ), + ); + }), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + Get.find().changePassword(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textChangePassword), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // Get.find().changePassword(); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChangePassword), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart b/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart new file mode 100644 index 0000000..063281b --- /dev/null +++ b/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/privacy_policy_controller.dart'; + +class PrivacyPolicyBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => PrivacyPolicyController(), + ); + } +} diff --git a/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart b/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart new file mode 100644 index 0000000..1e2c33d --- /dev/null +++ b/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class PrivacyPolicyController extends GetxController { + //TODO: Implement PrivacyPolicyController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/privacy_policy/views/privacy_policy_view.dart b/lib/app/modules/privacy_policy/views/privacy_policy_view.dart new file mode 100644 index 0000000..076c3b4 --- /dev/null +++ b/lib/app/modules/privacy_policy/views/privacy_policy_view.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import '../controllers/privacy_policy_controller.dart'; + +class PrivacyPolicyView extends GetView { + const PrivacyPolicyView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: "Privacy Policy", + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.all(15), + child: Card( + surfaceTintColor: Colors.white, + elevation: 5.0, + child: /*ListView.builder( + itemBuilder: (context, index) { + return Column( + children: [ + Text(privacyPolicy.title, + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + privacyPolicy.description, + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + ], + ); + },),*/ + + ListView( + // Wrap the Card with a ListView for vertical scrolling + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // first paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // second paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // third paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // forth paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + ], + ), + ), + ], + ), + ), + + /*Card( + surfaceTintColor: Colors.white, + elevation: 5.0, + child: ListView( + // Wrap the Card with a ListView for vertical scrolling + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // first paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // second paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // third paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // forth paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + // CustomButton( + ], + ), + ), + ], + ), + ),*/ + ), + ); + } +} diff --git a/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart b/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart new file mode 100644 index 0000000..01a74c9 --- /dev/null +++ b/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/qr_setting_controller.dart'; +// +// class QrSettingBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => QrSettingController(), +// ); +// } +// } diff --git a/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart b/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart new file mode 100644 index 0000000..72910c9 --- /dev/null +++ b/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart @@ -0,0 +1,130 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +// import 'package:image_gallery_saver/image_gallery_saver.dart'; +// import 'package:image_picker/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; +// import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:screenshot/screenshot.dart'; +import 'package:share_plus/share_plus.dart'; +// import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:screenshot/screenshot.dart'; +// import 'package:screenshot/screenshot.dart'; +// import 'package:share_plus/share_plus.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +// import 'package:share_plus/share_plus.dart'; + + + +class QrSettingController extends GetxController { + // + // + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); + + Barcode? result; + // + // QRViewController? qrController; + + ScreenshotController screenshotController = ScreenshotController(); + + List qrList = [ + QRSetting(name: "Muhammad Bilal", accountNumber: "MSISDN: ********** 2222"), + ]; + + Future saveAssetImage() async { + Uint8List? image = await screenshotController.capture(); + + if (image != null) { + // await ImageGallerySaver.saveImage(image); + Toasty.error("QR Image save successfully"); + } + } + + void shareQRImage() async { + try { + // + + var tempDir = await getTemporaryDirectory(); + + var image = await screenshotController.captureAndSave(tempDir.path); + + dp("Path ", image); + + if (image != null) { + Share.shareXFiles([XFile(image)]); + } + + // + } catch (e) { + if (kDebugMode) { + print('Error sharing asset image: $e'); + } + // Handle any errors + } + } + + void toggleFlash() { + // qrController?.toggleFlash(); + } + + Future? getFlashStatus() { + // return qrController?.getFlashStatus() ?? Future.value(false); + } + + Future scanfromImage() async { + + // var imagePath = await ImagePicker().pickImage(source: ImageSource.gallery); + + // var result = await qrController?.scanQrcodeFromImage(imagePath!.path); + + // qrController?.pauseCamera(); + // + // if (result != null && result.isNotEmpty) { + // Get.back(result: result.first); + // } else { + // Get.back(); + // Toasty.error("Please re scan data not fetch"); + // } + // + // dp("Result Image", result?.map((e) => e).toList()); + // + // dp("Result Image", result?.length); + } + + @override + void dispose() { + // qrController?.dispose(); + super.dispose(); + } + + // void onQRViewCreated(QRViewController p1) { + // // + // + // qrController = p1; + // + // update(); + // + // qrController?.scannedDataStream.listen((scanData) { + // result = scanData; + // + // qrController?.pauseCamera(); + // + // dp("Barcode result", result?.code); + // + // if (result != null) { + // Get.back(result: result!.code); + // } + // + // // + // }); + // } +} + +class QRSetting { + String name = ""; + String accountNumber = ""; + + QRSetting({this.name = "", this.accountNumber = ""}); +} diff --git a/lib/app/modules/qr_setting/views/qr_scan_screen.dart b/lib/app/modules/qr_setting/views/qr_scan_screen.dart new file mode 100644 index 0000000..8339422 --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_scan_screen.dart @@ -0,0 +1,322 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +// import 'package:qr_code_scanner/qr_code_scanner.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../controllers/qr_setting_controller.dart'; + +class QrScanScreen extends GetView { + const QrScanScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + title: "QR SCAN", + ), + body: GetBuilder(builder: (controller) { + return Column( + children: [ + // Expanded( + // flex: 5, + // child: QRView( + // key: controller.qrKey, + // onQRViewCreated: controller.onQRViewCreated, + // overlay: QrScannerOverlayShape(), + // ), + // ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + GestureDetector( + onTap: () async { + await controller.scanfromImage(); + }, + child: const Icon(Icons.image)), + GestureDetector( + onTap: () { + controller.toggleFlash(); + }, + child: FutureBuilder( + future: controller.getFlashStatus(), + builder: (context, snapshot) { + return Icon( + (snapshot.data ?? false) + ? Icons.flash_off + : Icons.flash_on, + ); + }, + ), + ), + ], + )), + ], + ); + }), + ); + } +} +// +// // import 'dart:async'; +// +// // import 'package:flutter/material.dart'; +// // import 'package:get/get.dart'; +// // import 'package:qr_flutter/qr_flutter.dart'; +// // import 'package:uco_ciihive/app/core/utils/logs_utils.dart'; +// // import 'package:uco_ciihive/app/custom_widgets/custom_app_bar.dart'; +// // import 'package:mobile_scanner/mobile_scanner.dart'; +// // import 'scanner_buttons.dart'; +// +// // class QrScanScreen extends StatefulWidget { +// // const QrScanScreen({super.key}); +// +// // @override +// // State createState() => _QrScanScreenState(); +// // } +// +// // class _QrScanScreenState extends State { +// // // +// +// // final MobileScannerController scanController = MobileScannerController( +// // formats: [BarcodeFormat.qrCode], +// // useNewCameraSelector: true, +// // facing: CameraFacing.back, +// // ); +// +// // StreamSubscription? _subscription; +// +// // late final AppLifecycleListener _listener; +// +// // Barcode? _barcode; +// +// // @override +// // void initState() { +// +// // initScanner(); +// // listenAppLifeState(); +// +// // super.initState(); +// // } +// +// // @override +// // Future dispose() async { +// // unawaited(_subscription?.cancel()); +// // _subscription = null; +// // _listener.dispose(); +// +// // super.dispose(); +// +// // await scanController.dispose(); +// // } +// +// // void listenAppLifeState() { +// // _listener = AppLifecycleListener( +// // onStateChange: _onStateChanged, +// // ); +// // } +// +// // void initScanner() { +// // _subscription = scanController.barcodes.listen(_handleBarcode); +// +// // unawaited(scanController.start()); +// // } +// +// // Future _onStateChanged(AppLifecycleState state) async { +// // dp("Scanner state", state.name); +// // switch (state) { +// // case AppLifecycleState.hidden: +// // case AppLifecycleState.paused: +// // case AppLifecycleState.detached: +// // return; +// // case AppLifecycleState.resumed: +// // _subscription = scanController.barcodes.listen(_handleBarcode); +// +// // unawaited(scanController.start()); +// // case AppLifecycleState.inactive: +// // unawaited(_subscription?.cancel()); +// // _subscription = null; +// // unawaited(scanController.stop()); +// // } +// // } +// +// // void _handleBarcode(BarcodeCapture barcodes) { +// // _barcode = barcodes.barcodes.firstOrNull; +// // dp("Barcode Result Raw", _barcode?.rawValue); +// // dp("Barcode Display Value", _barcode?.displayValue); +// +// // setState(() {}); +// // } +// +// // @override +// // Widget build(BuildContext context) { +// // final scanWindow = Rect.fromCenter( +// // center: MediaQuery.sizeOf(context).center(Offset.zero), +// // width: 200, +// // height: 200, +// // ); +// // return Scaffold( +// // appBar: DashBoardAppBar( +// // onBackButtonPressed: () { +// // Get.back(); +// // }, +// // ), +// // body: Stack( +// // fit: StackFit.expand, +// // children: [ +// // Center( +// // child: MobileScanner( +// // fit: BoxFit.contain, +// // controller: scanController, +// // scanWindow: scanWindow, +// // errorBuilder: (context, error, child) { +// // // return ScannerErrorWidget(error: error); +// // return const SizedBox( +// // child: Text("Error Widget"), +// // ); +// // }, +// // overlayBuilder: (context, constraints) { +// // return Padding( +// // padding: const EdgeInsets.all(16.0), +// // child: Align( +// // alignment: Alignment.bottomCenter, +// // child: +// // ScannedBarcodeLabel(barcodes: scanController.barcodes), +// // ), +// // ); +// // }, +// // ), +// // ), +// // ValueListenableBuilder( +// // valueListenable: scanController, +// // builder: (context, value, child) { +// // if (!value.isInitialized || +// // !value.isRunning || +// // value.error != null) { +// // return const SizedBox( +// // child: Text("No init Scanner"), +// // ); +// // } +// +// // return CustomPaint( +// // painter: ScannerOverlay(scanWindow: scanWindow), +// // ); +// // }, +// // ), +// // Align( +// // alignment: Alignment.bottomCenter, +// // child: Padding( +// // padding: const EdgeInsets.all(16.0), +// // child: Row( +// // mainAxisAlignment: MainAxisAlignment.spaceEvenly, +// // children: [ +// // ToggleFlashlightButton(controller: scanController), +// // SwitchCameraButton(controller: scanController), +// // ], +// // ), +// // ), +// // ), +// // ], +// // ), +// // ); +// // } +// // } +// +// // class ScannerOverlay extends CustomPainter { +// // const ScannerOverlay({ +// // required this.scanWindow, +// // this.borderRadius = 12.0, +// // }); +// +// // final Rect scanWindow; +// // final double borderRadius; +// +// // @override +// // void paint(Canvas canvas, Size size) { +// // // TODO: use `Offset.zero & size` instead of Rect.largest +// // // we need to pass the size to the custom paint widget +// // final backgroundPath = Path()..addRect(Rect.largest); +// +// // final cutoutPath = Path() +// // ..addRRect( +// // RRect.fromRectAndCorners( +// // scanWindow, +// // topLeft: Radius.circular(borderRadius), +// // topRight: Radius.circular(borderRadius), +// // bottomLeft: Radius.circular(borderRadius), +// // bottomRight: Radius.circular(borderRadius), +// // ), +// // ); +// +// // final backgroundPaint = Paint() +// // ..color = Colors.black.withOpacity(0.5) +// // ..style = PaintingStyle.fill +// // ..blendMode = BlendMode.dstOut; +// +// // final backgroundWithCutout = Path.combine( +// // PathOperation.difference, +// // backgroundPath, +// // cutoutPath, +// // ); +// +// // final borderPaint = Paint() +// // ..color = Colors.white +// // ..style = PaintingStyle.stroke +// // ..strokeWidth = 4.0; +// +// // final borderRect = RRect.fromRectAndCorners( +// // scanWindow, +// // topLeft: Radius.circular(borderRadius), +// // topRight: Radius.circular(borderRadius), +// // bottomLeft: Radius.circular(borderRadius), +// // bottomRight: Radius.circular(borderRadius), +// // ); +// +// // // First, draw the background, +// // // with a cutout area that is a bit larger than the scan window. +// // // Finally, draw the scan window itself. +// // canvas.drawPath(backgroundWithCutout, backgroundPaint); +// // canvas.drawRRect(borderRect, borderPaint); +// // } +// +// // @override +// // bool shouldRepaint(ScannerOverlay oldDelegate) { +// // return scanWindow != oldDelegate.scanWindow || +// // borderRadius != oldDelegate.borderRadius; +// // } +// // } +// +// // class ScannedBarcodeLabel extends StatelessWidget { +// // const ScannedBarcodeLabel({ +// // super.key, +// // required this.barcodes, +// // }); +// +// // final Stream barcodes; +// +// // @override +// // Widget build(BuildContext context) { +// // return StreamBuilder( +// // stream: barcodes, +// // builder: (context, snapshot) { +// // final scannedBarcodes = snapshot.data?.barcodes ?? []; +// +// // if (scannedBarcodes.isEmpty) { +// // return const Text( +// // 'Scan something!', +// // overflow: TextOverflow.fade, +// // style: TextStyle(color: Colors.wh'ite), +// // ); +// // } +// +// // return Text( +// // scannedBarcodes.first.displayValue ?? 'No display value.', +// // overflow: TextOverflow.fade, +// // style: const TextStyle(color: Colors.white), +// // ); +// // }, +// // ); +// // } +// // } diff --git a/lib/app/modules/qr_setting/views/qr_setting_view.dart b/lib/app/modules/qr_setting/views/qr_setting_view.dart new file mode 100644 index 0000000..7d0ed47 --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_setting_view.dart @@ -0,0 +1,116 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:screenshot/screenshot.dart'; +// import 'package:screenshot/screenshot.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/qr_setting_controller.dart'; + +class QrSettingView extends GetView { + const QrSettingView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textQRSetting), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + children: [ + const SizedBox(height: 20), + Align( + alignment: Alignment.center, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textYourUCOQR), + style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textUCOQRContent), + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 14), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Screenshot( + controller: controller.screenshotController, + child: Container( + color: Colors.white, + padding: const EdgeInsets.all(12), + child: QrImageView( + data: jsonEncode({"phoneNumber": SessionCache.instance.depositAccountList.first.padAdrsmobphone}), + version: QrVersions.auto, + size: 200.0, + ), + ), + ), + const SizedBox(height: 20), + Text( + SessionCache.instance.depositAccountList.first.mbmBkmstitle, + style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textQrAccountNumber), + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w400, fontSize: 14), + textAlign: TextAlign.center, + ), + ], + ), + ), + persistentFooterButtons: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + onPressed: () { + controller.saveAssetImage(); + }, + icon: SvgPicture.asset( + AppAssets.ic_download, + height: 15, + width: 15, + ), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSavetoGallery), + buttonColor: AppColors.colorButton, + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.white, fontWeight: FontWeight.w400, fontSize: 13), + iconPadding: const EdgeInsets.only(left: 5), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + ), + SizedBox( + child: CustomButton( + onPressed: () { + controller.shareQRImage(); + }, + iconPadding: const EdgeInsets.only(left: 5), + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textShareQRCode), + buttonColor: AppColors.colorSkipBtn, + sideBorder: const BorderSide(width: 1, color: AppColors.colorBorderSkipBtn), + icon: SvgPicture.asset(AppAssets.ic_share, height: 15, width: 15), + ), + ), + ], + ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/qr_setting/views/qr_view_screen.dart b/lib/app/modules/qr_setting/views/qr_view_screen.dart new file mode 100644 index 0000000..38956fb --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_view_screen.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; + +class QrViewScreen extends StatelessWidget { + const QrViewScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SizedBox( + width: context.getWidth, + height: context.getHeight, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text("Qr View Screen"), + const SizedBox( + height: 20, + ), + QrImageView( + data: ''' +{ +"channelCode":"01", +"porOrgacode":"0006", +"email":"", +"isOtpRequire":false, +"pinType":"C_TRANPIN" +} +''', + version: QrVersions.auto, + size: 200.0, + ), + const SizedBox( + height: 20, + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/qr_setting/views/scanner_buttons.dart b/lib/app/modules/qr_setting/views/scanner_buttons.dart new file mode 100644 index 0000000..3aa66c3 --- /dev/null +++ b/lib/app/modules/qr_setting/views/scanner_buttons.dart @@ -0,0 +1,169 @@ +import 'package:flutter/material.dart'; +// import 'package:image_picker/image_picker.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; + +class AnalyzeImageFromGalleryButton extends StatelessWidget { + const AnalyzeImageFromGalleryButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return IconButton( + color: Colors.white, + icon: const Icon(Icons.image), + iconSize: 32.0, + onPressed: () async { + // final ImagePicker picker = ImagePicker(); + // + // final XFile? image = await picker.pickImage( + // source: ImageSource.gallery, + // ); + + // if (image == null) { + // return; + // } + // + // final BarcodeCapture? barcodes = await controller.analyzeImage( + // image.path, + // ); + // + // if (!context.mounted) { + // return; + // } + + // final SnackBar snackbar = barcodes != null + // ? const SnackBar( + // content: Text('Barcode found!'), + // backgroundColor: Colors.green, + // ) + // : const SnackBar( + // content: Text('No barcode found!'), + // backgroundColor: Colors.red, + // ); + + // ScaffoldMessenger.of(context).showSnackBar(snackbar); + }, + ); + } +} + +class StartStopMobileScannerButton extends StatelessWidget { + const StartStopMobileScannerButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return IconButton( + color: Colors.white, + icon: const Icon(Icons.play_arrow), + iconSize: 32.0, + onPressed: () async { + await controller.start(); + }, + ); + } + + return IconButton( + color: Colors.white, + icon: const Icon(Icons.stop), + iconSize: 32.0, + onPressed: () async { + await controller.stop(); + }, + ); + }, + ); + } +} + +class SwitchCameraButton extends StatelessWidget { + const SwitchCameraButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return const SizedBox.shrink(); + } + + final int? availableCameras = state.availableCameras; + + if (availableCameras != null && availableCameras < 2) { + return const SizedBox.shrink(); + } + + final Widget icon; + + switch (state.cameraDirection) { + case CameraFacing.front: + icon = const Icon(Icons.camera_front); + case CameraFacing.back: + icon = const Icon(Icons.camera_rear); + } + + return IconButton( + iconSize: 32.0, + icon: icon, + onPressed: () async { + await controller.switchCamera(); + }, + ); + }, + ); + } +} + +class ToggleFlashlightButton extends StatelessWidget { + const ToggleFlashlightButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return const SizedBox.shrink(); + } + switch (state.torchState) { + case TorchState.off: + return IconButton( + color: Colors.white, + iconSize: 32.0, + icon: const Icon(Icons.flash_off), + onPressed: () async { + await controller.toggleTorch(); + }, + ); + case TorchState.on: + return IconButton( + color: Colors.white, + iconSize: 32.0, + icon: const Icon(Icons.flash_on), + onPressed: () async { + await controller.toggleTorch(); + }, + ); + case TorchState.unavailable: + return const Icon( + Icons.no_flash, + color: Colors.grey, + ); + case TorchState.auto: + throw UnimplementedError(); + } + }, + ); + } +} diff --git a/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart b/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart new file mode 100644 index 0000000..edc7baf --- /dev/null +++ b/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/recipient_details_controller.dart'; + +class RecipientDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => RecipientDetailsController(), + ); + } +} diff --git a/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart b/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart new file mode 100644 index 0000000..9a2669d --- /dev/null +++ b/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart @@ -0,0 +1,64 @@ +import 'dart:ffi'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitRequestModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitResponseModel.dart'; + +import '../../../routes/app_pages.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + +class RecipientDetailsController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + Rx transactionSubmitRequestModel = + TransactionSubmitRequestModel + .empty() + .obs; + String exchangeRate = ""; + String endingBalance = ""; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel.value = (arguments != null + ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? + TransactionSubmitRequestModel.empty() + : TransactionSubmitRequestModel.empty()); + exchangeRate = + (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future sendTransaction() async { + // ServerResponse response = await repository + // .sendTransactionStep2(transactionSubmitRequestModel.value); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // + // TransactionSubmitResponseModel responseModel = + // TransactionSubmitResponseModel.fromMap(response.response); + // + // transitionUpdate.value++; + // + // dp("Transition value is", transitionUpdate.value); + + // CustomDialog.showTransactionSuccessDialog( + // context, + // responseModel.mbmBkmsbalance.toString(), + // exchangeRate, + // transactionSubmitRequestModel.value, + // ); + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + } +} diff --git a/lib/app/modules/recipient_details/views/recipient_details_view.dart b/lib/app/modules/recipient_details/views/recipient_details_view.dart new file mode 100644 index 0000000..fb8e3fb --- /dev/null +++ b/lib/app/modules/recipient_details/views/recipient_details_view.dart @@ -0,0 +1,265 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +import '../controllers/recipient_details_controller.dart'; + +class RecipientDetailsView extends GetView { + const RecipientDetailsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransaction), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Column( + children: [ + Stack(children: [ + Container( + height: 70, + decoration: + const BoxDecoration(color: AppColors.colorPrimary)), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Card( + color: AppColors.colorGrey50, + margin: + const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textRecipient), + style: + Theme + .of(context) + .textTheme + .bodyMedium), + )), + Expanded( + flex: 4, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, right: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + controller.transactionSubmitRequestModel + .value.crMbmBkmstitle, + style: Theme + .of(context) + .textTheme + .titleSmall, + ), + const SizedBox(height: 5), + Text( + controller.transactionSubmitRequestModel + .value.crMbmBkmsnumber, + style: + Theme + .of(context) + .textTheme + .bodySmall, + ), + ], + ), + )), + ], + )), + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(top: 80, left: 20, right: 20), + child: Card( + color: AppColors.colorGrey50, + margin: + const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(15), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConformation), + style: Theme + .of(context) + .textTheme + .titleSmall + ?.copyWith( + fontWeight: FontWeight.w600, + fontSize: 20)), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textAccountNumber), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textSendingAmount), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCurrency), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textMessage), + style: Theme + .of(context) + .textTheme + .bodyMedium), + ], + ), + )), + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, right: 12.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + controller + .transactionSubmitRequestModel + .value + .crMbmBkmsnumber, + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .sgtGntramtfc + .toString(), + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .crPcrCurrdesc, + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .otdTrancomment, + style: Theme + .of(context) + .textTheme + .bodySmall), + ], + ), + )), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + CustomButton( + onPressed: () { + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textConfirm), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 20), + ), + CustomButton( + onPressed: () { + Get.back(); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textCancel), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme + .of(context) + .textTheme + .labelLarge + ?.copyWith(color: AppColors.black), + sideBorder: const BorderSide( + width: 1, + color: AppColors.colorBorderSkipBtn), + buttonPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 20)), + ], + ), + ], + )), + ), + ), + ]), + ], + ); + }), + ); + } +} diff --git a/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart b/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart new file mode 100644 index 0000000..50f73aa --- /dev/null +++ b/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sample_fields_controller.dart'; + +class SampleFieldsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SampleFieldsController(), + ); + } +} diff --git a/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart b/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart new file mode 100644 index 0000000..20dd819 --- /dev/null +++ b/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_date_time_picker.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_input_field.dart'; + +class SampleFieldsController extends GetxController { + //TODO: Implement SampleFieldsController + late CustomInputFieldCustom userNameField; + + late CustomInputFieldCustom passwordField; + + late BuildContext context; + + late CustomDateTimePicker dateField; + + late CustomDropDown genderField; + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/sample_fields/views/sample_fields_view.dart b/lib/app/modules/sample_fields/views/sample_fields_view.dart new file mode 100644 index 0000000..606d7a0 --- /dev/null +++ b/lib/app/modules/sample_fields/views/sample_fields_view.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_date_time_picker.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/modules/login/views/shared/login_widget.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../controllers/sample_fields_controller.dart'; + +class SampleFieldsView extends GetView { + const SampleFieldsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + String className = runtimeType.toString().split('.').last; + return Scaffold( + persistentFooterButtons: [ + BottomNavigationBar( + backgroundColor: AppColors.colorSecondary.withOpacity(0.1), + elevation: 0, + type: BottomNavigationBarType.fixed, + items: [ + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs( + context, + TranslationKeys.makeTranslation(TranslationKeys.textFindUAgent), + AppAssets.ic_cyber_security, + () { + Get.toNamed(Routes.O_T_P_SCREEN); + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + }, + context.textTheme.bodySmall!.copyWith(fontSize: 12), + ), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textQRPay), AppAssets.ic_QR, () { + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textHelp), AppAssets.ic_client, () { + Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + // BottomNavigationBarItem( + // icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textContactUs), AppAssets.ic_contact_us, () { + // showBottomSheet(context); + // }), + // label: '', + // ), + ], + ), + ], + body: SingleChildScrollView( + child: Column( + children: [ + GestureDetector( + onTap: () { + // showCurrencyDialog(context); + }, + child: Align(alignment: Alignment.centerRight, child: Padding(padding: const EdgeInsets.only(right: 8.0, left: 8.0), child: Container(decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), height: 60, width: 30, child: Padding(padding: const EdgeInsets.only(top: 28.0), child: SvgPicture.asset(AppAssets.ic_arrow_down, height: 20, width: 20)))))), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: Column( + children: [ + const SizedBox(height: 20), + SvgPicture.asset(AppAssets.lg_logo_black, height: 100, width: 100), + const SizedBox(height: 10), + controller.userNameField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + labelText: "User Name", + ), + const SizedBox(height: 10), + controller.passwordField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + labelText: "Password", + requiredPasswordIcon: true, + isPassword: true, + ), + const SizedBox(height: 10), + controller.dateField = CustomDateTimePicker( + refKey: FormFieldConstants.instance().getFormKey("${className}dateField"), + controller: FormFieldConstants.instance().getController("${className}dateField"), + labelText: "picker", + ), + const SizedBox(height: 10), + controller.genderField = CustomDropDown( + listData: [DropDown("id1", "Label1"), DropDown("id2", "Label2"), DropDown("id3", "Label3")].obs, + labelText: "Gender", + isRequired: true, + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart new file mode 100644 index 0000000..ff6fc00 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_otp_controller.dart'; + +class SignUpScreenOTPBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenOTPController(), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart new file mode 100644 index 0000000..6bed8c9 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step1_controller.dart'; + +class SignUpScreenStep1Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep1Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart new file mode 100644 index 0000000..cb238cc --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step2_controller.dart'; + +class SignUpScreenStep2Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep2Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart new file mode 100644 index 0000000..41b03c3 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step3_controller.dart'; + +class SignUpScreenStep3Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep3Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart new file mode 100644 index 0000000..3c04c30 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/models/SignupOtpRequest.dart'; +import 'package:uco_mobile_poc/app/models/resend_ot_login_model.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; + +class SignUpScreenOTPController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + TextEditingController pinPutController = TextEditingController(); + + RegisterRequest firstStepData = RegisterRequest.empty(); + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? RegisterRequest.empty() : RegisterRequest.empty()); + } + Future validatePinAndNavigate() async { + hideKeyBoard(); + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + SignupOtpRequest request = SignupOtpRequest( + username: firstStepData.username, + email: firstStepData.email, + obpPincode: pinPutController.text, + // obpPintype: AppConstants.PIN_TYPE_SIGNUP, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + ); + + ServerResponse response = await repository.signupStep2(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP2, + arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: firstStepData, + } + ); + + clearControllersOTP(); + } + + void clearControllersOTP() { + pinPutController.clear(); + } + + void resenOtp() async { + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resentOtpLoginSignUp( + ResendOtpLoginModel( + userRole: firstStepData.userRole, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: firstStepData.email, + isOtpRequire: false, + phone: firstStepData.phone, + pinType: 'C_TRANPIN', + username: firstStepData.email, + ), + ); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.setOnRestart( + () {}, + ); + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenOTPView"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart new file mode 100644 index 0000000..ee57b89 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:string_validator/string_validator.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/utils/fields_utils.dart'; + +class SignUpScreenStep1Controller extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + + late InputField lastNameField; + late InputField passwordField; + late InputField confirmPasswordField; + late InputField emailField; + late InputField phoneNumberField; + + /// map for country wise phone number length + final RxString selectedCountryCode = 'US'.obs; + final Map countryPhoneMap = { + 'US': 10, + 'PK': 11, + 'It': 11, + }; + + + bool validatePhoneNumber(String countryCode, String phoneNumber) { + if (countryPhoneMap.containsKey(countryCode)) { + return phoneNumber.length == countryPhoneMap[countryCode]; + } + return false; + } + + bool validate() { + bool isValid = FieldValidation.validateAll([firstNameField, passwordField, confirmPasswordField, emailField, phoneNumberField]); + return isValid; + } + + void validateAndSendRequest() async { + hideKeyBoard(); + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + bool otherValidation = true; + if (!AppUtils.isPasswordValid(passwordField.getCustomText(), 8)) { + passwordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(confirmPasswordField.getCustomText(), 8)) { + confirmPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!isEmail(emailField.getCustomText())) { + emailField.setError("Invalid email"); + otherValidation = false; + } + if (!otherValidation) { + return; + } + if (passwordField.getCustomText() != confirmPasswordField.getCustomText()) { + Toasty.error("Passwords didn't matched"); + return; + } + + if (!validatePhoneNumber(selectedCountryCode.value, phoneNumberField.getCustomText())) { + Toasty.error("Invalid phone number length"); + return; + } + + RegisterRequest request = RegisterRequest( + email: emailField.getCustomText(), + password: passwordField.getCustomText(), + username: firstNameField.getCustomText(), + phone: phoneNumberField.getCustomText(isPrefixRequired: true, isCountryCodeRequired: true), + name: "", + channelCode: RequestConstants.channelCode, + userRole: AppConstants.ROLE_USER, + porOrgacode: RequestConstants.porOrgacode, + isOtpRequired: false, + ); + ServerResponse response = await repository.signupStep1(request); + + if (response.errorCode == "ERR_USER_0007") { + Get.toNamed(Routes.SIGN_UP_SCREEN_OTP, arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + }); + return; + } + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.SIGN_UP_SCREEN_OTP, + arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + } + ); + } + clearTextControllerStep1() { + firstNameField.clear(); + passwordField.clear(); + confirmPasswordField.clear(); + emailField.clear(); + phoneNumberField.clear(); + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep1View"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart new file mode 100644 index 0000000..0e689f1 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/dialogs/custom_loading.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/models/SignupStep3RequestModel.dart'; +import 'package:uco_mobile_poc/app/models/product_model.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; + +class SignUpScreenStep2Controller extends GetxController { + final String IDEN_NUMBER = "01"; + final String IDEN_TAX_PAYER_ID = "02"; + final String IDEN_PASSPORT = "03"; + + String dpmcode = ''; + + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + late InputField lastNameField; + late InputField nameAddressField; + late InputField selectIdentityTypeField; + late InputField identityNumberField; + late InputField taxPayerIdField; + late InputField passportField; + String? selectedCountryCode; + + + RxList identityDropdownList = [].obs; + DropDown? currentIdentityValue; + + RegisterRequest firstStepData = RegisterRequest.empty(); + + late InputField countryFeild; + + late InputField provinceFeild; + + late InputField cityFeild; + + late InputField currencyCodesFelid; + + var countryList = [ + {"name": "Pakistan", "code": "PK"}, + {"name": "United States of America", "code": "USA"} + ].map((e) => DropDown(e["code"]!, e["code"]!)).toList(); + + List provinceList = [ + { + "country": "PK", + "province": ["Sindh", "Punjab", "Gilgit Baltistan", "KPK", "Baluchistan"] + }, + { + "country": "USA", + "province": ["California", "Florida", "Hawaii"] + }, + ] + .expand( + (Map e) => (e["province"] as List) + .map((e1) => DropDown(e["country"]!, e1)), + ) + .toList(); + + + List currencyList = []; + List currencyListDropDown = []; + + List getProvinceList(String country) { + return provinceList + .where((element) => element.id == country) + .toList(); + } + + // getProvinceList(String country) { + // return provinceList + // .where((DropDown? element) => element!.id == country) + // .toList(); + // } + + List cityList = [ + { + "province": "Sindh", + "city": ["Karachi", "Ladkana"] + }, + { + "province": "Punjab", + "city": ["Lahore"] + }, + { + "province": "Gilgit Baltistan", + "city": ["Gilgit"] + }, + { + "province": "California", + "city": ["California"] + }, + { + "province": "Florida", + "city": ["Florida"] + }, + { + "province": "Hawaii", + "city": ["Hawaii"] + }, + ] + .expand( + (Map e) => (e["city"] as List) + .map((e1) => DropDown(e["province"]!, e1)), + ) + .toList(); + + @override + void onInit() { + super.onInit(); + identityDropdownList.value = [ + DropDown(IDEN_NUMBER, TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber)), + DropDown(IDEN_TAX_PAYER_ID, TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID)), + DropDown(IDEN_PASSPORT, TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID)), + ]; + } + + @override + Future onReady() async { + super.onReady(); + getCurrencyList(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? RegisterRequest.empty() : RegisterRequest.empty()); + } + + updateIdentityValue(DropDown? identityDropDowModel) { + currentIdentityValue = identityDropDowModel; + update(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([firstNameField, lastNameField, nameAddressField, selectIdentityTypeField, + currencyCodesFelid, + ]); + + if (currentIdentityValue != null) { + if (currentIdentityValue!.id == IDEN_NUMBER) { + isValid = isValid && FieldValidation.validateAll([identityNumberField]); + } else if (currentIdentityValue!.id == IDEN_TAX_PAYER_ID) { + isValid = isValid && FieldValidation.validateAll([taxPayerIdField]); + } else if (currentIdentityValue!.id == IDEN_PASSPORT) { + isValid = isValid && FieldValidation.validateAll([passportField]); + } + } + + return isValid; + } + + String getIdentification() { + if (currentIdentityValue!.id == IDEN_NUMBER) { + return identityNumberField.getCustomText(); + } else if (currentIdentityValue!.id == IDEN_TAX_PAYER_ID) { + return taxPayerIdField.getCustomText(); + } else if (currentIdentityValue!.id == IDEN_PASSPORT) { + return passportField.getCustomText(); + } + return ""; + } + + void validateAndSendRequest() async { + hideKeyBoard(); + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + SignupStep3RequestModel signupStep3RequestModel = + SignupStep3RequestModel(username: firstStepData.username, + email: firstStepData.email, phone: firstStepData.phone, + channelCode: firstStepData.channelCode, porOrgacode: firstStepData.porOrgacode, + address: nameAddressField.getCustomText(), + name: '${firstNameField.getCustomText()} ${lastNameField.getCustomText()}', + identificationType: currentIdentityValue!.id, identificationNumber: getIdentification(), + userRole: AppConstants.ROLE_USER, isKycAdded: false, kycType: "", + kycDocumentId1: "", kycDocumentId2: "", dmpProdcode: dpmcode); + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP3, + arguments: { + AppConstants.SIGN_UP_SECOND_STEP_DATA: signupStep3RequestModel, + } + ); + } + clearTextControllerStep2() { + firstNameField.clear(); + lastNameField.clear(); + nameAddressField.clear(); + selectIdentityTypeField.clear(); + identityNumberField.clear(); + taxPayerIdField.clear(); + passportField.clear(); + update(); + } + + void updateCurrency(DropDown? item) { + dpmcode = item!.id; + update(); + } + + getCurrencyList() async { + try { + var productResponce = await repository.getCurrencyList(); + + if (productResponce.isError) { + hideLoader(); + + Toasty.error(productResponce.errorMsg); + return; + } + + currencyList = ProductDepositModel.productListFromJson(productResponce.response); + + currencyListDropDown = currencyList.map((e) => DropDown(e.dmpProdcode, e.dmpProddesc, e)).toList(); + + hideLoader(); + + update(); + } catch (e, s) { + dp("Error in get product $e", s); + hideLoader(); + Toasty.error("Something went worng please try again"); + } + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep2View"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart new file mode 100644 index 0000000..d123eb3 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart @@ -0,0 +1,170 @@ +// import 'package:camera/camera.dart'; +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/SignupStep3RequestModel.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/utils/fields_utils.dart'; +import 'sign_up_screen_otp_controller.dart'; + +enum signDocTypeScreen { cnic, passport, driving } + +class SignUpScreenStep3Controller extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + RxList documentTypeTabList = [].obs; + RxString frontPath = "".obs; + RxString backPath = "".obs; + + Rx docTypeScreen = signDocTypeScreen.cnic.obs; + SignupStep3RequestModel signupStep3RequestModel = SignupStep3RequestModel.empty(); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + signupStep3RequestModel = (arguments != null ? arguments[AppConstants.SIGN_UP_SECOND_STEP_DATA] ?? SignupStep3RequestModel.empty() : SignupStep3RequestModel.empty()); + } + + updateDocTypeScreen(signDocTypeScreen type) { + if (type != docTypeScreen.value) { + frontPath.value = ""; + backPath.value = ""; + docTypeScreen.value = type; + } + } + + updateFrontPath(path) { + frontPath.value = path; + } + + updateBackPath(path) { + backPath.value = path; + } + + void updateDocs(String path, bool isFront, signDocTypeScreen docType) { + if (isFront) { + updateFrontPath(path); + } else { + updateBackPath(path); + } + } + + String getKycType() { + if (docTypeScreen == signDocTypeScreen.cnic) { + return AppConstants.IDEN_TYPE_CNIC; + } else if (docTypeScreen == signDocTypeScreen.passport) { + return AppConstants.IDEN_TYPE_PASSPORT; + } else if (docTypeScreen == signDocTypeScreen.driving) { + return AppConstants.IDEN_TYPE_DRIVING_LICIENCE; + } + return ""; + } + + void skipAndSubmit() { + signupStep3RequestModel.kycType = ""; + signupStep3RequestModel.isKycAdded = false; + signupStep3RequestModel.kycDocumentId1 = ""; + signupStep3RequestModel.kycDocumentId2 = ""; + sendRequest(); + } + + void validateAndSubmit() { + hideKeyBoard(); + if (frontPath.value.isEmpty) { + Toasty.error("Please upload front image"); + return; + } else if (docTypeScreen.value != signDocTypeScreen.passport) { + if (backPath.value.isEmpty) { + Toasty.error("Please upload back image"); + return; + } + } + + signupStep3RequestModel.kycType = getKycType(); + signupStep3RequestModel.isKycAdded = true; + signupStep3RequestModel.kycDocumentId1 = frontPath.value; + signupStep3RequestModel.kycDocumentId2 = backPath.value; + sendRequest(); + } + + Future sendRequest() async { + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.toString()); + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.porOrgacode + "Rehan"); + signupStep3RequestModel.porOrgacode = "0005"; + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.porOrgacode + "Rehan"); + ServerResponse response = await repository.signupStep3(signupStep3RequestModel); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + CustomDialog.showSuccessDialog( + description: TranslationKeys.makeTranslation(TranslationKeys.textSignUpDescriptionDailog), + onTapPositive: () { + Get.back(); + // Get.offAndToNamed(Routes.LOGIN_SCREEN); + // step1Controller.clearTextControllerStep1(); + // otpController.clearControllersOTP(); + // step2Controller.clearTextControllerStep2(); + Get.delete(); + Get.delete(); + Get.delete(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }); + } + + var step1Controller = Get.find(); + var otpController = Get.find(); + var step2Controller = Get.find(); + + /// Flash Light work + late CameraController _controller; + late List cameras; + var isFlashOn = false.obs; + + @override + void onInit() { + super.onInit(); + initializeCamera(); + } + + Future initializeCamera() async { + cameras = await availableCameras(); + _controller = CameraController(cameras[0], ResolutionPreset.low, enableAudio: false); + await _controller.initialize(); + + // Restore flash state if it was previously on + if (_controller.value.flashMode == FlashMode.torch) { + isFlashOn(true); + } + } + + Future toggleFlashlight() async { + if (_controller.value.isInitialized) { + if (_controller.value.flashMode == FlashMode.off) { + await _controller.setFlashMode(FlashMode.torch); + isFlashOn(true); + } else { + await _controller.setFlashMode(FlashMode.off); + isFlashOn(false); + } + } + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep3View"); + _controller.dispose(); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/views/shared/camera_screen.dart b/lib/app/modules/sign_up/views/shared/camera_screen.dart new file mode 100644 index 0000000..fba8293 --- /dev/null +++ b/lib/app/modules/sign_up/views/shared/camera_screen.dart @@ -0,0 +1,95 @@ +import 'dart:io'; + +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_camera_overlay_new/flutter_camera_overlay.dart'; +import 'package:flutter_camera_overlay_new/model.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; + +import '../../controllers/sign_up_screen_step3_controller.dart'; + +class CameraOverlayScreen extends StatelessWidget { + final bool isFront; + final signDocTypeScreen docType; + + CameraOverlayScreen({super.key, required this.isFront, required this.docType}); + + SignUpScreenStep3Controller controller = Get.find(); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: FutureBuilder?>( + future: availableCameras(), + builder: (context, snapshot) { + if (snapshot.hasData) { + if (snapshot.data == null) { + return const Align( + alignment: Alignment.center, + child: Text( + 'No camera found', + style: TextStyle(color: Colors.black), + )); + } + + return CameraOverlay( + snapshot.data!.first, + CardOverlay.byFormat(OverlayFormat.cardID1), + (XFile file) { + showDialog( + context: context, + barrierColor: Colors.black, + builder: (context) { + CardOverlay overlay = CardOverlay.byFormat(OverlayFormat.cardID1); + return AlertDialog( + actionsAlignment: MainAxisAlignment.center, + backgroundColor: Colors.black, + title: const Text('Capture', style: TextStyle(color: Colors.white), textAlign: TextAlign.center), + actions: [ + OutlinedButton(onPressed: () => Navigator.of(context).pop(), child: const Icon(Icons.close)), + OutlinedButton( + onPressed: () { + Get.put(SignUpScreenStep3Controller()).updateDocs(file.path, isFront, docType); + Navigator.of(context).pop(); + Navigator.pop(context); + }, + child: const Icon(Icons.done)), + ], + content: SizedBox( + width: double.infinity, + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(file.path), + ), + )), + ), + ), + ), + ); + }, + ); + }, + info: 'Position your ID card within the rectangle and ensure the image is perfectly readable.', + label: 'Scanning ID Card', + ); + } else { + return const Align( + alignment: Alignment.center, + child: Text( + 'Fetching cameras', + style: TextStyle(color: Colors.black), + )); + } + }, + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart new file mode 100644 index 0000000..b5052f3 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/sign_up_screen_otp_controller.dart'; + +class SignUpScreenOTPView extends GetView { + const SignUpScreenOTPView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + controller.pinPutController.clear(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodyMedium?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textResend), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey))), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart new file mode 100644 index 0000000..65cf3f8 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/core/utils/phone_number_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/sign_up_screen_step1_controller.dart'; + +class SignUpScreenStep1View extends GetView { + const SignUpScreenStep1View({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // Get.put(() => AppRemoteDataSource()); + // Get.lazyPut(() => AppRepositoriesImpl(remoteDataSource: Get.find())); + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textSingUp), + onBackButtonPressed: () { + if (Navigator.canPop(context)) { + Get.back(); + controller.clearTextControllerStep1(); + } else { + SystemNavigator.pop(); + } + }, + ), + persistentFooterButtons: [ + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric( + vertical: 10, + ), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + ], + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column( + children: [ + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 8, + child: controller.firstNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}firstNameField"), + controller: FormFieldConstants.instance().getController("${className}firstNameField"), + hintText: "User Name", + labelText: TranslationKeys.makeTranslation("User Name"), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + const Spacer(), + Expanded( + flex: 8, + child: controller.lastNameField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}lastNameField"), + controller: FormFieldConstants.instance().getController("${className}lastNameField"), + hintText: "Enter last name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textLastName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + ], + ), + controller.passwordField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + hintText: "Enter password", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassword), + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.confirmPasswordField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}confirmPasswordField"), + controller: FormFieldConstants.instance().getController("${className}confirmPasswordField"), + hintText: "Enter password", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textConfirmPassword), + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.emailField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}emailField"), + controller: FormFieldConstants.instance().getController("${className}emailField"), + hintText: "Enter email", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmailID), + ), + controller.phoneNumberField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}phoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}phoneNumberField"), + hintText: "Enter phone number", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textCellNumber), + keyboardType: TextInputType.phone, + inputFormatters: [LengthLimitingTextInputFormatter(PhoneNumberUtils.getPhoneNumberLength()), InputType.NUMBER], + // prefixText:AppUtils.formatPhoneNumber(PhoneNumberUtils.phoneCode), + prefixCode: PhoneNumberUtils.phoneCode, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + isCountryPicker: true, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart new file mode 100644 index 0000000..beb3f97 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart @@ -0,0 +1,253 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_input_field.dart'; +import '../../../models/identity_drop_down_model.dart'; +import '../../../res/app_theme.dart'; +import '../controllers/sign_up_screen_step2_controller.dart'; + +class SignUpScreenStep2View extends GetView { + const SignUpScreenStep2View({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var border = OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor), borderRadius: BorderRadius.circular(50)); + var dropDowDecoration = InputDecoration( + border: border, + enabledBorder: border, + focusedBorder: border, + disabledBorder: border, + errorBorder: border, + ); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textSingUp), + onBackButtonPressed: () { + Get.back(); + controller.clearTextControllerStep2(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(vertical: 12), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + ], + body: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: GetBuilder(builder: (controller) { + return SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 8, + child: controller.firstNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}firstNameField"), + controller: FormFieldConstants.instance().getController("${className}firstNameField"), + hintText: "Enter first name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textFirstName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + const Spacer(), + Expanded( + flex: 8, + child: controller.lastNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}lastNameField"), + controller: FormFieldConstants.instance().getController("${className}lastNameField"), + hintText: "Enter last name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textLastName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + ], + ), + + controller.countryFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}selectCountry"), + controller: FormFieldConstants.instance() + .getController("${className}selectCountry"), + labelText: "Select Country", + isDropDown: true, + hintText: "Select Country", + dropDownType: DropDownType.SPECIAL, + items: controller.countryList, + onItemSelected: (item) { + controller.selectedCountryCode = item?.id; + controller.update(); + }, + // onItemSelected: (item) {}, + ), + + controller.provinceFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}provinceField"), + controller: FormFieldConstants.instance() + .getController("${className}provinceField"), + labelText: "Select Province", + isDropDown: true, + hintText: "Select Province", + dropDownType: DropDownType.SPECIAL, + items: controller.selectedCountryCode == null + ? [] + : controller.getProvinceList(controller.selectedCountryCode!), + onItemSelected: (item) {}, + // items: controller.getProvinceList('USA'), + // onItemSelected: (item) { + // controller.selectedCountryCode = item?.id; + // controller.update(); + // }, + // items: controller.getProvinceList("USA"), + // onItemSelected: (item) {}, + ), + + controller.cityFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}cityField"), + controller: FormFieldConstants.instance() + .getController("${className}cityField"), + labelText: "Select City", + isDropDown: true, + hintText: "Select City", + dropDownType: DropDownType.SPECIAL, + items: controller.cityList, + onItemSelected: (item) { + controller.updateIdentityValue(item); + }, + ), + + controller.nameAddressField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}nameAddressField"), + controller: FormFieldConstants.instance().getController("${className}nameAddressField"), + hintText: "Enter address", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textAddress), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.addressFieldLength)], + ), + + controller.currencyCodesFelid = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}currencyCodesFelid"), + controller: FormFieldConstants.instance().getController("${className}currencyCodesFelid"), + labelText: "Select Default Currency", + isDropDown: true, + hintText: "Select Default Currency", + dropDownType: DropDownType.SPECIAL, + items: controller.currencyListDropDown as List?, + onItemSelected: (item) { + controller.updateCurrency(item); + }, + ), + + controller.selectIdentityTypeField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectIdentificationField"), + controller: FormFieldConstants.instance().getController("${className}selectIdentificationField"), + labelText: "Select Identification", + isDropDown: true, + hintText: "Select Identification", + dropDownType: DropDownType.SPECIAL, + items: controller.identityDropdownList, + onItemSelected: (item) { + controller.updateIdentityValue(item); + }, + ), + + Column( + children: [ + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_NUMBER, + child: controller.identityNumberField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}identityNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber), + hintText: "Enter Identity number", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_TAX_PAYER_ID, + child: controller.taxPayerIdField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}taxPayerIdField"), + controller: FormFieldConstants.instance().getController("${className}taxPayerIdField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID), + hintText: "Enter taxpayer id", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_PASSPORT, + child: controller.passportField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passportField"), + controller: FormFieldConstants.instance().getController("${className}passportField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID), + hintText: "Enter passport number", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + ], + ), + + controller.currentIdentityValue?.id == identityType.identity + ? controller.identityNumberField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}identityNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber), + ) as InputField + : const SizedBox(), + controller.currentIdentityValue?.id == identityType.passport + ? controller.taxPayerIdField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}taxPayerIdField"), + controller: FormFieldConstants.instance().getController("${className}taxPayerIdField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID), + ) as InputField + : const SizedBox(), + controller.currentIdentityValue?.id == identityType.ssntaxpayer + ? controller.passportField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}passportField"), + controller: FormFieldConstants.instance().getController("${className}passportField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID), + ) as InputField + : const SizedBox(), + ], + ), + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart new file mode 100644 index 0000000..7e07699 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart @@ -0,0 +1,264 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_text.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/views/shared/camera_screen.dart'; +import 'package:uco_mobile_poc/app/res/app_theme.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/sign_up_screen_step3_controller.dart'; + +class SignUpScreenStep3View extends GetView { + final String imagePath; + + const SignUpScreenStep3View({this.imagePath = "", Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUploadKYC), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () async { + controller.validateAndSubmit(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 40), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + const SizedBox(width: 15), + CustomButton( + onPressed: () { + controller.skipAndSubmit(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSkipKYC), + icon: SvgPicture.asset(AppAssets.ic_next, height: 15, width: 15), + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13), + iconPadding: const EdgeInsets.only(left: 10), + buttonPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + buttonColor: AppColors.colorSkipBtn), + ], + ), + ), + ], + body: Obx(() { + return Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText(TranslationKeys.makeTranslation(TranslationKeys.textChooseDocumentType), style: AppThemeData.labelStyle), + const SizedBox(height: 5), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.cnic); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCNIC), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.cnic ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.cnic ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + const SizedBox(width: 10), + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.driving); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDivingLicense), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.driving ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.driving ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + const SizedBox(width: 10), + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.passport); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textPassport), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.passport ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.passport ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + ], + ), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation( + TranslationKeys.textDocumentsDescription, + ), + style: AppThemeData.labelStyle, + ), + const SizedBox(height: 20), + CNICScreen(docType: controller.docTypeScreen.value), + const SizedBox(height: 15), + ], + ), + ); + }), + ); + }); + } +} + +class CNICScreen extends StatelessWidget { + const CNICScreen({super.key, required this.docType}); + + final signDocTypeScreen docType; + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Column( + children: [ + SizedBox( + height: 120, + child: Row( + children: [ + Expanded( + flex: 10, + child: GestureDetector( + onTap: () async { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CameraOverlayScreen( + isFront: true, + docType: docType, + ))).then((value) { + }); + }, + child: Card( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(AppAssets.ic_camera, height: 41, width: 41, fit: BoxFit.cover), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textFront), + style: AppThemeData.labelStyle, + ), + ], + ), + ), + ), + ), + signDocTypeScreen.passport == docType + ? const SizedBox() + : const SizedBox( + width: 10, + ), + signDocTypeScreen.passport == docType + ? const SizedBox() + : Expanded( + flex: 10, + child: GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CameraOverlayScreen(isFront: false, docType: docType), + ), + ).then((value) => {}); + }, + child: Card( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(AppAssets.ic_camera, height: 41, width: 41, fit: BoxFit.cover), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textBack), + style: AppThemeData.labelStyle, + ), + ], + ), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Obx(() { + return SizedBox( + height: 200, + width: context.getWidth, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (controller.frontPath.value.isEmpty) + ? const Spacer() + : Expanded( + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(controller.frontPath.value), + ), + )), + ), + ), + ), + + const SizedBox(width: 20), + + signDocTypeScreen.passport == docType + ? const SizedBox() + : (controller.backPath.value.isEmpty) + ? const Spacer() + : Expanded( + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(controller.backPath.value), + ), + )), + ), + ), + ), + ], + ), + ); + }), + ], + ); + } + ); + } + } diff --git a/lib/app/modules/speed_dial/src/simple_speed_dial.dart b/lib/app/modules/speed_dial/src/simple_speed_dial.dart new file mode 100644 index 0000000..d964965 --- /dev/null +++ b/lib/app/modules/speed_dial/src/simple_speed_dial.dart @@ -0,0 +1,372 @@ +import 'package:flutter/material.dart'; + +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +class SpeedDial extends StatefulWidget { + const SpeedDial({ + Key? key, + required this.child, + required this.speedDialChildren, + this.labelsStyle, + this.labelsBackgroundColor, + this.controller, + this.closedForegroundColor, + this.openForegroundColor, + this.closedBackgroundColor, + this.openBackgroundColor, + }) : super(key: key); + + final Widget child; + + /// A list of [SpeedDialChild] to display when the [SpeedDial] is open. + final List speedDialChildren; + + /// Specifies the [SpeedDialChild] label text style. + final TextStyle? labelsStyle; + + /// The background color of the labels. + final Color? labelsBackgroundColor; + + /// An animation controller for the [SpeedDial]. + /// + /// Provide an [AnimationController] to control the animations + /// from outside the [SpeedDial] widget. + final AnimationController? controller; + + /// The color of the [SpeedDial] button foreground when closed. + /// + /// The [SpeedDial] foreground will animate to this color when the user + /// closes the speed dial. + final Color? closedForegroundColor; + + /// The color of the [SpeedDial] button foreground when opened. + /// + /// The [SpeedDial] foreground will animate to this color when the user + /// opens the speed dial. + final Color? openForegroundColor; + + /// The color of the [SpeedDial] button background when closed. + /// + /// The [SpeedDial] background will animate to this color when the user + /// closes the speed dial. + final Color? closedBackgroundColor; + + /// The color of the [SpeedDial] button background when open. + /// + /// The [SpeedDial] background will animate to this color when the user + /// opens the speed dial. + final Color? openBackgroundColor; + + @override + State createState() { + return _SpeedDialState(); + } +} + +class _SpeedDialState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _backgroundColorAnimation; + late Animation _foregroundColorAnimation; + final List> _speedDialChildAnimations = + >[]; + + @override + void initState() { + _animationController = widget.controller ?? + AnimationController( + vsync: this, duration: const Duration(milliseconds: 100)); + _animationController.addListener(() { + if (mounted) { + setState(() {}); + } + }); + + _backgroundColorAnimation = ColorTween( + begin: widget.closedBackgroundColor, + end: widget.openBackgroundColor, + ).animate(_animationController); + + _foregroundColorAnimation = ColorTween( + begin: widget.closedForegroundColor, + end: widget.openForegroundColor, + ).animate(_animationController); + + final double fractionOfOneSpeedDialChild = + 1.0 / widget.speedDialChildren.length; + for (int speedDialChildIndex = 0; + speedDialChildIndex < widget.speedDialChildren.length; + ++speedDialChildIndex) { + final List> tweenSequenceItems = + >[]; + + final double firstWeight = + fractionOfOneSpeedDialChild * speedDialChildIndex; + if (firstWeight > 0.0) { + tweenSequenceItems.add(TweenSequenceItem( + tween: ConstantTween(0.0), + weight: firstWeight, + )); + } + + tweenSequenceItems.add(TweenSequenceItem( + tween: Tween(begin: 0.0, end: 1.0), + weight: fractionOfOneSpeedDialChild, + )); + + final double lastWeight = fractionOfOneSpeedDialChild * + (widget.speedDialChildren.length - 1 - speedDialChildIndex); + if (lastWeight > 0.0) { + tweenSequenceItems.add(TweenSequenceItem( + tween: ConstantTween(1.0), weight: lastWeight)); + } + + _speedDialChildAnimations.insert( + 0, + TweenSequence(tweenSequenceItems) + .animate(_animationController)); + } + + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // + + int speedDialChildAnimationIndex = 0; + + return _animationController.isDismissed + ? GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Container( + width: 60, + height: 60, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(14), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == TextDirection.ltr ? 16 : 0, + left: Directionality.of(context) == TextDirection.rtl ? 16 : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all(color: AppColors.colorPrimary, width: 2), + ), + child: widget.child, + ), + ) + : GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: OverflowBox( + maxWidth: MediaQuery.sizeOf(context).width + 32, + child: Container( + color: Colors.black.withOpacity(0.4), + width: MediaQuery.sizeOf(context).width + 32, + child: Column( + mainAxisSize: _animationController.isDismissed + ? MainAxisSize.max + : MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (!_animationController.isDismissed) + Padding( + padding: EdgeInsets.only( + right: Directionality.of(context) == TextDirection.ltr + ? 24 + : 0, + left: Directionality.of(context) == TextDirection.rtl + ? 24 + : 0, + ), + child: GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: widget.speedDialChildren + .map((SpeedDialChild speedDialChild) { + final Widget speedDialChildWidget = Opacity( + opacity: _speedDialChildAnimations[ + speedDialChildAnimationIndex] + .value, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (speedDialChild.label != null) + Padding( + padding: const EdgeInsets.only( + right: 16.0 - 4.0), + child: GestureDetector( + onTap: () => _onTap(speedDialChild), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0), + child: Text( + speedDialChild.label!, + style: widget.labelsStyle, + ), + ), + ), + ), + ScaleTransition( + scale: _speedDialChildAnimations[ + speedDialChildAnimationIndex], + child: GestureDetector( + onTap: () => _onTap(speedDialChild), + child: Container( + width: 45, + height: 45, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(10), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == + TextDirection.ltr + ? 14 + : 0, + left: Directionality.of(context) == + TextDirection.rtl + ? 14 + : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all( + color: AppColors.colorPrimary, + width: 2), + ), + child: speedDialChild.child, + ), + ), + ), + ], + ), + ); + speedDialChildAnimationIndex++; + return speedDialChildWidget; + }).toList(), + ), + ), + ), + GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Container( + width: 60, + height: 60, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(14), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == TextDirection.ltr + ? 32 + : 0, + left: Directionality.of(context) == TextDirection.rtl + ? 32 + : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all( + color: AppColors.colorPrimary, width: 2), + ), + child: widget.child, + ), + ), + SizedBox(height: 24), + ], + ), + ), + ), + ); + } + + void _onTap(SpeedDialChild speedDialChild) { + if (speedDialChild.closeSpeedDialOnPressed) { + _animationController.reverse(); + } + speedDialChild.onPressed.call(); + } + +// Padding( +// padding: const EdgeInsets.symmetric(vertical: 4.0), +// child: FloatingActionButton( +// heroTag: speedDialChildAnimationIndex, +// mini: true, +// foregroundColor: speedDialChild.foregroundColor, +// backgroundColor: speedDialChild.backgroundColor, +// onPressed: () => _onTap(speedDialChild), +// child: speedDialChild.child, +// ), +// ) +} + +class SpeedDialChild { + const SpeedDialChild({ + required this.child, + required this.onPressed, + this.foregroundColor, + this.backgroundColor, + this.label, + this.closeSpeedDialOnPressed = true, + }); + + /// A widget to display as the [SpeedDialChild]. + final Widget child; + + /// A callback to be executed when the [SpeedDialChild] is pressed. + final Function onPressed; + + /// The [SpeedDialChild] foreground color. + final Color? foregroundColor; + + /// The [SpeedDialChild] background color. + final Color? backgroundColor; + + /// The text displayed next to the [SpeedDialChild] when the [SpeedDial] is open. + final String? label; + + /// Whether the [SpeedDial] should close after the [onPressed] callback of + /// [SpeedDialChild] is called. + /// + /// Defaults to [true]. + final bool closeSpeedDialOnPressed; +} diff --git a/lib/app/modules/splash/bindings/splash_screen_binding.dart b/lib/app/modules/splash/bindings/splash_screen_binding.dart new file mode 100644 index 0000000..957064a --- /dev/null +++ b/lib/app/modules/splash/bindings/splash_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/splash_screen_controller.dart'; + +class SplashScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SplashScreenController(), + ); + } +} diff --git a/lib/app/modules/splash/controllers/splash_screen_controller.dart b/lib/app/modules/splash/controllers/splash_screen_controller.dart new file mode 100644 index 0000000..d1f6c25 --- /dev/null +++ b/lib/app/modules/splash/controllers/splash_screen_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class SplashScreenController extends GetxController { + //TODO: Implement SplashScreenController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/splash/views/splash_screen_view.dart b/lib/app/modules/splash/views/splash_screen_view.dart new file mode 100644 index 0000000..fbee77b --- /dev/null +++ b/lib/app/modules/splash/views/splash_screen_view.dart @@ -0,0 +1,49 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +class SplashScreenView extends StatefulWidget { + const SplashScreenView({Key? key}) : super(key: key); + + @override + State createState() => _SplashScreenViewState(); +} + +class _SplashScreenViewState extends State { + @override + void initState() { + super.initState(); + Timer(const Duration(seconds: 4), () => Get.offAllNamed(Routes.INTRO_SCREEN)); + } + + @override + Widget build(BuildContext context) { + dp("Width int splash", {MediaQuery.sizeOf(Get.context!).width}); + dp("Height init splash ", MediaQuery.sizeOf(Get.context!).height); + return Scaffold( + backgroundColor: AppColors.colorPrimary, + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: AppDimensions.screenHorizontalPadding, + vertical: AppDimensions.screenVerticalPadding), + child: Center( + child: AnimatedCrossFade( + duration: const Duration(milliseconds: 2000), + firstChild: SvgPicture.asset(AppAssets.lg_uco_logo_white), + secondChild: const Text( + '', + ), + alignment: Alignment.center, + crossFadeState: CrossFadeState.showFirst), + ), + ), + ); + } +} diff --git a/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart b/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart new file mode 100644 index 0000000..e9d8d50 --- /dev/null +++ b/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/transaction_history_controller.dart'; + +class TransactionHistoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => TransactionHistoryController(), + ); + } +} diff --git a/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart b/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart new file mode 100644 index 0000000..1f012c2 --- /dev/null +++ b/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class TransactionHistoryController extends GetxController { + //TODO: Implement TransactionHistoryController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/transaction_history/shared/hository_list_widget.dart b/lib/app/modules/transaction_history/shared/hository_list_widget.dart new file mode 100644 index 0000000..4b36445 --- /dev/null +++ b/lib/app/modules/transaction_history/shared/hository_list_widget.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; + +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +class HistoryListViewWidget extends StatelessWidget { + bool isCredit = false; + String type = ""; + String title = ""; + String shortTitle = ""; + String description = ""; + String dateTime = ""; + String balance = ""; + String dateMonth = ""; + String dateOfMonth = ""; + String year = ""; + String transactionId = ""; + String transactionIdNumber = ""; + Function()? onTap; + + HistoryListViewWidget({ + Key? key, + this.isCredit = false, + this.type = "", + this.title = "", + this.dateTime = "", + this.balance = "", + this.shortTitle = "", + this.description = "", + this.year = "", + this.dateMonth = "", + this.dateOfMonth = "", + this.transactionId = "", + this.transactionIdNumber = "", + this.onTap, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 3), + child: Card( + elevation: 3, + color: AppColors.colorGrey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Container( + /**/ decoration: BoxDecoration( + color: AppColors.colorText.withOpacity(0.03), + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Padding( + padding: + EdgeInsets.only(left: 10.0, top: 5, right: 10.0, bottom: 5), + child: Column( + children: [ + Row( + children: [ + Container( + padding: EdgeInsets.only(top: 5), + decoration: BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + children: [ + Text(dateMonth, + style: Theme.of(context).textTheme.labelSmall), + Text(dateOfMonth, + style: Theme.of(context).textTheme.titleMedium), + Container( + decoration: BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(10), + bottomLeft: Radius.circular(10)), + ), + padding: EdgeInsets.symmetric( + vertical: 3, horizontal: 15), + height: 20, + child: Text(year, + style: + Theme.of(context).textTheme.labelSmall), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LimitedBox( + maxWidth: 120, + child: Text("\$ $balance", + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .titleSmall)), + Row( + children: [ + Container( + height: 25, + width: 2.2, + color: AppColors.colorButton, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + LimitedBox( + maxWidth: 120, + child: Text("Transaction ID", + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .labelSmall)), + LimitedBox( + maxWidth: 120, + child: Text(transactionIdNumber, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .labelSmall)), + ], + ), + ), + ], + ), + ], + ), + ), + const Expanded(child: SizedBox()), + Icon(Icons.arrow_forward_ios_outlined, + size: 20, color: AppColors.colorText), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/transaction_history/views/transaction_history_view.dart b/lib/app/modules/transaction_history/views/transaction_history_view.dart new file mode 100644 index 0000000..65dce9b --- /dev/null +++ b/lib/app/modules/transaction_history/views/transaction_history_view.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/modules/transaction_history/shared/hository_list_widget.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; +import '../controllers/transaction_history_controller.dart'; + +class TransactionHistoryView extends GetView { + const TransactionHistoryView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textTransactionHistory), + onBackButtonPressed: () { + Get.back(); + }, + ), + + // AppBar( + // title: const Text('TransactionHistoryView'), + // centerTitle: true, + // ), + body: Padding( + padding: EdgeInsets.symmetric( + vertical: AppDimensions.screenVerticalPadding, + horizontal: AppDimensions.screenHorizontalPadding), + child: ListView.builder( + itemCount: 1, + itemBuilder: (context, index) { + return HistoryListViewWidget( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT); + }, + dateMonth: "Mar", + dateOfMonth: "17", + balance: "100", + year: "2024", + transactionIdNumber: "12345", + ); + }, + ), + ), + ); + } +} diff --git a/lib/app/modules/u_received/bindings/u_received_binding.dart b/lib/app/modules/u_received/bindings/u_received_binding.dart new file mode 100644 index 0000000..1162990 --- /dev/null +++ b/lib/app/modules/u_received/bindings/u_received_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_received_controller.dart'; + +class UReceivedBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UReceivedController(), + ); + } +} diff --git a/lib/app/modules/u_received/controllers/u_received_controller.dart b/lib/app/modules/u_received/controllers/u_received_controller.dart new file mode 100644 index 0000000..ae090d1 --- /dev/null +++ b/lib/app/modules/u_received/controllers/u_received_controller.dart @@ -0,0 +1,363 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/DepositAccountResponse.dart'; +import 'package:uco_mobile_poc/app/models/accept_receive_transaction.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../models/u_recived_responce_model.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + +class UReceivedController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + UReceivedResponseData? selectedTransaction; + RxList uReceivedData = RxList.empty(); + String className = ""; + late InputField depositAccountField; + late InputField referenceCodeField; + TextEditingController pinPutController = TextEditingController(); + + TextEditingController referenceCodeController = TextEditingController(); + + // late InputField userTransactionPinField; + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + @override + Future onReady() async { + super.onReady(); + + Future.delayed(Duration.zero).then((value) { + selectedDepositAccount.value = allDepositAccounts.first.data as DepositAccount; + + depositAccountField.setText(allDepositAccounts.first.label); + + getPendingTransition(); + }); + } + + @override + void onInit() { + super.onInit(); + + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + + allDepositAccounts.add( + DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + ); + } + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + getPendingTransition(); + + dp("Data update", item); + } + + Future getPendingTransition() async { + ServerResponse response = await repository.getPendingTransition(selectedDepositAccount.value.mbmBkmsnumber); + dp("=========== u received request ", response.toString()); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + uReceivedData.assignAll(List.from(((response.response ?? []) as List).map((x) => UReceivedResponseData.fromMap(x)))); + + transitionUpdate.value++; + + dp("=========== u received request ", uReceivedData.toString()); + } + + void transactionPinDialog(BuildContext context, UReceivedController controller) { + clearController(); + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit reference number"); + return; + } + + Navigator.of(context, rootNavigator: true).pop(); + sendAcceptTransactionRequest(controller.pinPutController.text, controller.referenceCodeController.text); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + Future acceptTransaction(UReceivedResponseData data) async { + selectedTransaction = data; + transactionPinDialog(context, this); + } + + Future sendAcceptTransactionRequest(String pin, String referanceCode) async { + AcceptReceiveTransactionModel request = AcceptReceiveTransactionModel( + porOrgacode: SessionCache.instance.userInfo.porOrgacode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + cmpTranpin: pin, + cmpRefcode: referanceCode, + id: selectedTransaction!.id, + isAccepted: true, + ); + + ServerResponse response = await repository.acceptReceiveTransaction(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + showCongratulationDialogOtp(context); + } + + /// Reverse transaction method + Future reverseTransactionRequest(String sgtSentGntrnumber, String sgtSentNodeId) async { + // ReverseTransactionModel request = ReverseTransactionModel( + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // nodeId: sgtSentNodeId, + // sgtGntrnumber: sgtSentGntrnumber, + // ); + + ServerResponse response = await repository.reverseTransaction(sgtSentNodeId, sgtSentGntrnumber); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + showCongratulationDialogOtp(context); + } + + void clearController() { + pinPutController.clear(); + referenceCodeController.clear(); + } + + void showCongratulationDialogOtp(BuildContext context) { + Get.dialog( + responsiveWidget( + SizedBox( + width: context.getWidth, + child: Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textCongratulations), + style: Theme.of(context).textTheme.titleSmall, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + Text( + "Your transaction reverse successfully!", + style: Theme.of(context).textTheme.bodySmall, + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 60.0, right: 60.0), + child: CustomButton( + onPressed: () { + onPressDone(context); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + void onPressDone(BuildContext context) { + Navigator.of(context, rootNavigator: true).pop(); + clearController(); + getPendingTransition(); + transitionUpdate.value++; + } +} diff --git a/lib/app/modules/u_received/views/u_received_view.dart b/lib/app/modules/u_received/views/u_received_view.dart new file mode 100644 index 0000000..b699fa7 --- /dev/null +++ b/lib/app/modules/u_received/views/u_received_view.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_no_record.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_text.dart'; +import 'package:uco_mobile_poc/app/models/u_recived_responce_model.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +import '../controllers/u_received_controller.dart'; + +class UReceivedView extends GetView { + const UReceivedView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textPendingRemittance), style: Theme.of(context).textTheme.bodyMedium), + ), + controller.uReceivedData.isNotEmpty + ? Expanded( + flex: 1, + child: ListView.builder( + itemCount: controller.uReceivedData.length, + itemBuilder: (context, index) { + UReceivedResponseData data = controller.uReceivedData[index]; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 15.0), + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5.0)), border: Border.all(color: AppColors.colorGrey350, width: 1.5)), + child: ExpansionTile( + collapsedBackgroundColor: Colors.white, + tilePadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10), + dense: false, + // onExpansionChanged: controller.toggleExpansion(), + maintainState: true, + expandedAlignment: Alignment.topLeft, + expandedCrossAxisAlignment: CrossAxisAlignment.start, + childrenPadding: const EdgeInsets.all(10), + //tilePadding: EdgeInsets.all(8.0), + collapsedShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + // collapsedBackgroundColor: AppColors.colorGrey350, + shape: const Border(), + backgroundColor: AppColors.white, + leading: Padding( + padding: const EdgeInsets.only(top: 3.0), + child: Text("${data.drPcrCurrshort} ${data.sgtGntramt}", style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + trailing: const Icon( + Icons.keyboard_arrow_down_outlined, + size: 25, + color: AppColors.colorGrey700, + ), + title: Text(data.drmbmBkmstitle ?? "-", style: Theme.of(context).textTheme.labelMedium), + children: [ + // Text("${data.drPcrCurrshort} ${data.sgtGntramt}", style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorButton)), + // const SizedBox(height: 5), + // Row( + // children: [ + // Text("Memo: ", style: Theme.of(context).textTheme.labelSmall), + // Text(data..toString(), style: Theme.of(context).textTheme.labelSmall), + // ], + // ), + const SizedBox(height: 5), + Row( + children: [ + Text("Sent: ", style: Theme.of(context).textTheme.labelSmall), + Text(data.drSgtGntrdate.toString(), style: Theme.of(context).textTheme.labelSmall), + ], + ), + const SizedBox(height: 5), + Text("Expires Date: ${data.expSgtGntrdate} ", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Transaction-ID: ${data.sgtSentGntrnumber.toString()}${data.sgtSentNodeId}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Sender: ${data.drmbmBkmstitle}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + onTap: () { + controller.reverseTransactionRequest(data.sgtSentGntrnumber, data.sgtSentNodeId); + }, + child: Column( + children: [SvgPicture.asset(AppAssets.ic_cross_option, height: 22, width: 22), const SizedBox(height: 5), CustomText(TranslationKeys.makeTranslation(TranslationKeys.textReverse))], + ), + ), + const SizedBox(width: 30), + InkWell( + onTap: () { + controller.acceptTransaction(data); + }, + child: Column( + children: [SvgPicture.asset(AppAssets.ic_tick_option, height: 22, width: 22), const SizedBox(height: 5), CustomText(TranslationKeys.makeTranslation(TranslationKeys.textReceived))], + ), + ), + ], + ), + ], + ), + ), + ); + }, + ), + ) + : const Center(child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment")), + ], + ); + }), + ); + } +} diff --git a/lib/app/modules/u_send/bindings/u_send_binding.dart b/lib/app/modules/u_send/bindings/u_send_binding.dart new file mode 100644 index 0000000..2d8f95c --- /dev/null +++ b/lib/app/modules/u_send/bindings/u_send_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_send_controller.dart'; + +class USendBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => USendController(), + ); + } +} diff --git a/lib/app/modules/u_send/controllers/u_send_controller.dart b/lib/app/modules/u_send/controllers/u_send_controller.dart new file mode 100644 index 0000000..91c0a2f --- /dev/null +++ b/lib/app/modules/u_send/controllers/u_send_controller.dart @@ -0,0 +1,394 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +// import 'package:flutter_contacts/contact.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/AccountInquiryResponseModel.dart'; +import 'package:uco_mobile_poc/app/models/DepositAccountResponse.dart'; +import 'package:uco_mobile_poc/app/models/ExchangeRate.dart'; +import 'package:uco_mobile_poc/app/models/SendTransactionStep1ResponseModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionPinRequestModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitRequestModel.dart'; +import 'package:uco_mobile_poc/app/modules/qr_setting/controllers/qr_setting_controller.dart'; +import 'package:uco_mobile_poc/app/modules/qr_setting/views/qr_scan_screen.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +class USendController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + TextEditingController referenceCodeController = TextEditingController(); + final AppRepositories repository = Get.find(); + + BuildContext context = Get.context as BuildContext; + + String OPTION_PHONE = "01"; + + String OPTION_EMAIL = "02"; + + //drop down + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + RxList allRecipientDetailOptions = RxList.empty(); + Rx selectedRecipientDetailOption = DropDown.empty().obs; + + RxList allCurrencieList = RxList.empty(); + DropDown selectedCurrency = DropDown.empty(); + RxString currencySymbol = "".obs; + + // Contact? selectedContact; + ExchangeRate? selectedExchangeRate; + String receiverAccountNumber = ""; + String receiverAccountTitle = ""; + + // fields + late InputField depositAccountField; + late InputField selectRecipientDetailField; + + // late InputField selectCurrencyField; + late InputField identityPhoneNumberField; + late InputField identityEmailField; + late InputField recipientCardNameField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + // @override + // void onInit() { + // super.onInit(); + // + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + // + // allDepositAccounts.add(DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + // } + // + // selectedDepositAccount.value = allDepositAccounts.first.data; + // + // allRecipientDetailOptions.value = [ + // DropDown(OPTION_PHONE, TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber)), + // DropDown(OPTION_EMAIL, TranslationKeys.makeTranslation(TranslationKeys.textEmail)), + // ]; + // + // for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + // ExchangeRate exchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + // allCurrencieList.add(DropDown(exchangeRate.pcrCurrcode, exchangeRate.pcrCurrdesc, exchangeRate)); + // } + // } + + @override + Future onReady() async { + super.onReady(); + + disposeAllResources(); + + updateSelectedDeposit(allDepositAccounts.elementAt(0)); + + Future.delayed(Duration.zero).then((value) { + depositAccountField.setText((allDepositAccounts.first.label)); + }); + } + + void disposeAllResources() { + depositAccountField.clear(); + selectRecipientDetailField.clear(); + // selectCurrencyField.clear(); + identityPhoneNumberField.clear(); + identityEmailField.clear(); + recipientCardNameField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + } + + void updateSelectedCurrency(/*DropDown? item*/ AccountInquiryResponseModel model) { + print("************************model>> $model"); + + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + print("************************elementAt(i).pcrCurrcode>> ${SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode}"); + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == model.pcrCurrcode) { + currencySymbol.value = SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrshort; + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void updateRecipientDetail(DropDown? item) { + selectedRecipientDetailOption.value = item!; + } + + Future selectContact() async { + dynamic result = await Get.toNamed(Routes.CONTACTS_SCREEN); + + // if ((result != null && result[AppConstants.SELECTED_CONTACT] != null)) { + // selectedContact = result[AppConstants.SELECTED_CONTACT]; + // identityPhoneNumberField.setText(AppUtils.formatPhoneNumber(selectedContact!.phones.first.number) /*"${selectedContact!.displayName} (${AppUtils.formatPhoneNumber(selectedContact!.phones.first.number + ")")}"*/); + // } + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + depositAccountField, + selectRecipientDetailField, + recipientCardNameField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + dp("Validate value", isValid); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + Future sendTransaction({navigate = true}) async { + // + + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drMbmBkmsnumber: selectedDepositAccount.value.mbmBkmsnumber, + // drMbmBkmstitle: selectedDepositAccount.value.mbmBkmstitle, + // drPcrCurrcode: selectedDepositAccount.value.pcrCurrcode, + // drPcrCurrdesc: selectedDepositAccount.value.pcrCurrdesc, + // drPcrCurrshort: selectedDepositAccount.value.pcrCurrshort, + // crMbmBkmsnumber: receiverAccountNumber, + // crMbmBkmstitle: receiverAccountTitle, + // crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectedDepositAccount.value.dmpProdcode, + // transType: "DR", + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + // otdTrancomment: messageField.getCustomText(), + // isOtpRequired: false, + // cmpRefcode: referenceCodeField.getCustomText(), + // ); + + TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + pinType: "TRAN", + transPincode: userTransactionPinField.getCustomText(), + isOtpRequired: false, + ); + + ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + + if (navigate) { + Get.toNamed(Routes.U_SEND_OTP, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + // } + ); + } else { + Fluttertoast.showToast( + msg: "OTP successfully send to your email address", + ); + } + } + + void clearTransaction() { + selectRecipientDetailField.clear(); + identityPhoneNumberField.clear(); + identityEmailField.clear(); + recipientCardNameField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + Future verifyAccountAgainstIt() async { + String valua = selectedRecipientDetailOption.value.id == OPTION_PHONE ? identityPhoneNumberField.getCustomText() : (selectedRecipientDetailOption.value.id == OPTION_EMAIL ? identityEmailField.getCustomText() : ""); + + bool isValid = true; + + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + if (!isValid) { + Toasty.error("Please input and then proceed"); + return; + } + ServerResponse response = await repository.fetchAccountInquiry(selectedRecipientDetailOption.value.id, valua); + + if (response.isError) { + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + identityPhoneNumberField.setError(response.errorMsg); + } else { + identityEmailField.setError(response.errorMsg); + } + // Toasty.error(response.errorMsg); + return; + } + + List responseData = response.response ?? []; + + List accountInquiryList; + accountInquiryList = AccountInquiryResponseModel.fromList(responseData); + + accountsDialog(accountInquiryList); + // AccountInquiryResponseModel transactionSubmitRequestModel = AccountInquiryResponseModel.fromMap(((response.response ?? {}) as Map).map((key, value) => MapEntry(key.toString(), value))); + } + + // void scanQr() async { + // Get.put(QrSettingController()); + // + // var scanResult = await Get.to(() => const QrScanScreen()); + // + // var resultJson = jsonDecode(scanResult); + // + // var accNumber = resultJson["phoneNumber"]; + // + // dp("Phone", accNumber); + // + // identityPhoneNumberField.setText(accNumber); + // + // verifyAccountAgainstIt(); + // } + + /// Accounts Dialogs...........u-send + void accountsDialog(List accountInquiryList) { + if (accountInquiryList.length == 1) { + receiverAccountTitle = accountInquiryList.first.mbmBkmstitle; + receiverAccountNumber = accountInquiryList.first.mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList.first); + return; + } + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + ListView.separated( + shrinkWrap: true, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + receiverAccountTitle = accountInquiryList[index].mbmBkmstitle; + receiverAccountNumber = accountInquiryList[index].mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList[index]); + Get.back(); + }, + child: Column(children: [ + Container( + height: 40, + width: double.infinity, + decoration: const BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("${accountInquiryList[index].mbmBkmstitle} (${accountInquiryList[index].pcrCurrshort})", style: Theme.of(context).textTheme.titleSmall), + Text(accountInquiryList[index].mbmBkmsnumber, style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + ), + ]), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 5)); + }, + itemCount: accountInquiryList.length), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/u_send/views/u_send_view.dart b/lib/app/modules/u_send/views/u_send_view.dart new file mode 100644 index 0000000..8c30e83 --- /dev/null +++ b/lib/app/modules/u_send/views/u_send_view.dart @@ -0,0 +1,582 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../controllers/u_send_controller.dart'; + +class USendView extends GetView { + const USendView({Key? key, this.showAppBar = true}) : super(key: key); + + final bool showAppBar; + + @override + Widget build(BuildContext context) { + Get.put(USendController()); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUSend), + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Obx(() { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.depositAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + controller.selectRecipientDetailField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectRecipientDetailField"), + controller: FormFieldConstants.instance().getController("${className}selectRecipientDetailField"), + labelText: "Recipient Detail", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allRecipientDetailOptions, + onItemSelected: (item) { + controller.updateRecipientDetail(item); + }, + ), + Column( + children: [ + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_PHONE, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityPhoneNumberField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + keyboardType: TextInputType.phone, + refKey: FormFieldConstants.instance().getFormKey("${className}identityPhoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityPhoneNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber), + hintText: "Select phone number", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // isCountryPicker: true, + suffixIcon: SizedBox( + width: 70, + child: Row( + children: [ + GestureDetector( + onTap: () { + // controller.scanQr(); + }, + child: const Icon(Icons.qr_code, size: 25, color: AppColors.colorPrimary)), + const SizedBox( + width: 8, + ), + InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + onTap: () { + controller.selectContact(); + }, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: SvgPicture.asset(AppAssets.ic_select_contact, height: 25, width: 25), + ), + ), + ], + ), + ), + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_EMAIL, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityEmailField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + keyboardType: TextInputType.emailAddress, + refKey: FormFieldConstants.instance().getFormKey("${className}identityEmailField"), + controller: FormFieldConstants.instance().getController("${className}identityEmailField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + hintText: "Enter your email", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + ], + ), + controller.recipientCardNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}recipientCardNameField"), + controller: FormFieldConstants.instance().getController("${className}recipientCardNameField"), + labelText: TranslationKeys.makeTranslation("Account Title"), + hintText: "Account title", + readOnly: true, + showCursor: false, + ), + // controller.selectCurrencyField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}selectCurrencyField"), + // controller: FormFieldConstants.instance().getController("${className}selectCurrencyField"), + // labelText: "Select Currency", + // isDropDown: true, + // hintText: "Select currency field", + // dropDownType: DropDownType.SPECIAL, + // items: controller.allCurrencieList, + // onItemSelected: (item) { + // controller.updateSelectedCurrency(item); + // }, + // suffixIcon: SizedBox( + // width: 100, + // height: 25, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Image.asset(AppAssets.ic_arrow_down_icon, height: 15, width: 15, color: AppColors.colorGrey500), + // const SizedBox(width: 10), + // Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Container( + // width: 50, + // decoration: const BoxDecoration( + // color: AppColors.colorPrimary, + // borderRadius: BorderRadius.only( + // topRight: Radius.circular(50), + // bottomRight: Radius.circular(50), + // ), + // ), + // child: Center( + // child: Text( + // controller.currencySymbol.value, + // style: const TextStyle(color: AppColors.white, fontSize: 12, fontWeight: FontWeight.w600), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ), + // ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.clearTransaction(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ); + }), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, USendController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, USendController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart b/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart new file mode 100644 index 0000000..2ed046e --- /dev/null +++ b/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_send_otp_controller.dart'; + +class USendOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => USendOtpController(), + ); + } +} diff --git a/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart b/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart new file mode 100644 index 0000000..205af8e --- /dev/null +++ b/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../routes/app_pages.dart'; + +class USendOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + // transactionSubmitRequestModel.pinType = "TRAN"; + // + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRate, + // } + ); + } + + + + void resenOtp() async { + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resendOtpUsend(ResendOtpUsendModel( + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: SessionCache.instance.userInfo.cmpUserId, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequired: false, + pctCstycode: SessionCache.instance.userInfo.pctCstycode, + pinType: 'C_TRANPIN', + )); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/u_send_otp/views/u_send_otp_view.dart b/lib/app/modules/u_send_otp/views/u_send_otp_view.dart new file mode 100644 index 0000000..43f0f83 --- /dev/null +++ b/lib/app/modules/u_send_otp/views/u_send_otp_view.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; +import '../controllers/u_send_otp_controller.dart'; + +class USendOtpView extends GetView { + const USendOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.put(USendController()).sendTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/user_activity/bindings/user_activity_binding.dart b/lib/app/modules/user_activity/bindings/user_activity_binding.dart new file mode 100644 index 0000000..9850db9 --- /dev/null +++ b/lib/app/modules/user_activity/bindings/user_activity_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/user_activity_controller.dart'; + +class UserActivityBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UserActivityController(), + ); + } +} diff --git a/lib/app/modules/user_activity/controllers/user_activity_controller.dart b/lib/app/modules/user_activity/controllers/user_activity_controller.dart new file mode 100644 index 0000000..e737648 --- /dev/null +++ b/lib/app/modules/user_activity/controllers/user_activity_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../custom_widgets/date_picker.dart'; +import '../../../models/UserActivity.dart'; +import '../../../models/UserActivityResponseModel.dart'; + +class UserActivityController extends GetxController { + RxBool isLoading = true.obs; + final dateFormat = DateFormat('yyyy-MM-dd'); + late BuildContext context; + + RxString fromDate = "----:--:--".obs; + RxString toDate = "----:--:--".obs; + + RxList userActivities = RxList.empty(); + final AppRepositories repository = Get.find(); + + /// Method for fetch User Activity Data + void fetchUserActivityData() async { + ServerResponse userActivityResponse = + await repository.fetchUserActivity(fromDate.value, toDate.value); + dp("msg user activity--------show data", userActivityResponse.toString()); + dp("msg user activity--------show data", userActivityResponse.runtimeType); + UserActivityResponseModel transactionsHistoryResponse = + UserActivityResponseModel.fromMap(userActivityResponse.response); + if (userActivityResponse.isError) { + Toasty.error( + TranslationKeys.makeTranslation(userActivityResponse.errorMsg)); + isLoading.value = false; + return; + } + + userActivities.assignAll(transactionsHistoryResponse.userActivity); + isLoading.value = false; + dp("User activity length", userActivities.length); + dp("User activity length", userActivities.toString()); + update(); + return; + } + + @override + Future onInit() async { + super.onInit(); + fromDate.value = + dateFormat.format(DateTime.now().subtract(const Duration(days: 30))); + toDate.value = dateFormat.format(DateTime.now()); + fetchUserActivityData(); + } + + void selectFromDate() async { + DateTime? fromDateTime = await DatePicker.showDatePicker(context); + if (fromDateTime != null) { + fromDate.value = dateFormat.format(fromDateTime); + toDate.value = "----:--:--"; + } + } + + void selectToDate() async { + if (fromDate.value == "----:--:--") { + Toasty.error(TranslationKeys.makeTranslation( + TranslationKeys.textSelectFromDateAndProceed)); + return; + } + DateTime? toDateTime = await DatePicker.showDatePicker(context); + if (toDateTime != null) { + toDate.value = dateFormat.format(toDateTime); + fetchUserActivityData(); + } + } +} diff --git a/lib/app/modules/user_activity/views/shared/date_time_dialog.dart b/lib/app/modules/user_activity/views/shared/date_time_dialog.dart new file mode 100644 index 0000000..73b9196 --- /dev/null +++ b/lib/app/modules/user_activity/views/shared/date_time_dialog.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; + +import '../../../../res/app_colors.dart'; + + +class DateTimeDialog extends StatelessWidget { + const DateTimeDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 30, + width: 50, + color: AppColors.colorText, + child: Column( + children: [ + SizedBox( + height: 15, + width: 30, + child: Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0)), + //this right here + child: SizedBox( + height: 33, + width: 90, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(bottom: 10.0), + child: Icon(Icons.close, + size: 40, color: AppColors.colorButton), + )), + const SizedBox( + height: 2, + ), + const Center( + child: Text( + "To verify your identify we sent a verification SMS. Please, enter the code we sent to", + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: AppColors.colorText), + ), + ), + const SizedBox( + height: 2, + ), + const Center( + child: Text( + "b***k@gmail.com/9232**", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: AppColors.colorText), + ), + ), + const SizedBox( + height: 2, + ), + Center( + child: InkWell( + onTap: () {}, + child: const Text( + "RESEND OTP", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: AppColors.colorPrimary), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_activity/views/user_activity_view.dart b/lib/app/modules/user_activity/views/user_activity_view.dart new file mode 100644 index 0000000..7706693 --- /dev/null +++ b/lib/app/modules/user_activity/views/user_activity_view.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/user_activity_controller.dart'; + +class UserActivityView extends GetView { + const UserActivityView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textUserActivityTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Column(children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: SizedBox( + width: 120, + child: Padding( + padding: const EdgeInsets.only(left: 0, right: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.calendar_month_rounded, + size: 18.0, + color: Colors.black.withOpacity(0.6), + ), + const SizedBox( + width: 5, + ), + Text( + controller.fromDate.value, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 12), + ), + ], + ), + ), + ), + onTap: () { + controller.selectFromDate(); + }, + ), + Container( + height: 30, // Adjust the height as needed + width: 1, // Adjust the width as needed + color: Colors.grey, // Adjust the color as needed + ), + InkWell( + child: SizedBox( + width: 120, + child: Padding( + padding: const EdgeInsets.only(left: 0, right: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.calendar_month_rounded, + size: 18.0, + color: Colors.black.withOpacity(0.6), + ), + const SizedBox( + width: 5, + ), + Text( + controller.toDate.value, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 12), + ), + ], + ), + ), + ), + onTap: () { + controller.selectToDate(); + }, + ), + ], + ), + ), + ), + ), + const SizedBox(height: 5), + controller.isLoading.value + ? const SizedBox() + : controller.userActivities.isNotEmpty + ? Expanded( + flex: 2, + child: ListView.builder( + itemCount: controller.userActivities.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + top: index == 0 ? 10 : 5, + bottom: index == + controller.userActivities.length - 1 + ? 10 + : 5), + child: Card( + surfaceTintColor: Colors.white, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + controller.userActivities[index].date + .toString(), + style: Theme.of(context) + .textTheme + .bodyMedium), + const SizedBox( + height: 10, + ), + Text( + controller + .userActivities[index].activity, + style: Theme.of(context) + .textTheme + .titleSmall), + const SizedBox( + height: 5, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityChannel)} ${controller.userActivities[index]?.channel ?? ' Found'}", + style: Theme.of(context) + .textTheme + .bodyMedium), + Text( + TranslationKeys.makeTranslation( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityDevice)}: ${controller.userActivities[index].deviceName}"), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + color: AppColors + .minusColor)), + ]), + ], + ), + ), + ), + ); + }, + ), + ) + : const CustomNoRecord( + title: "No Record Found", + description: + "We couldn't find any activity at this moment") + ]); + })); + } +} diff --git a/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart b/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart new file mode 100644 index 0000000..84c4c30 --- /dev/null +++ b/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get_state_manager/src/simple/get_view.dart'; + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../models/UserActivity.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/user_activity_controller.dart'; + +class UserActivityWidget extends GetView { + UserActivity userActivity; + + UserActivityWidget({required this.userActivity}); + + @override + Widget build(BuildContext context) { + return Card( + surfaceTintColor: Colors.white, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(userActivity.date.toString(), + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox( + height: 10, + ), + Text(userActivity.activity, + style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: 5, + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityChannel)}: ${userActivity.channel}", + style: Theme.of(context).textTheme.bodyMedium), + Text( + TranslationKeys.makeTranslation( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityDevice)}: ${userActivity.deviceName}"), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColors.minusColor)), + ]), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/user_profile/bindings/user_profile_binding.dart b/lib/app/modules/user_profile/bindings/user_profile_binding.dart new file mode 100644 index 0000000..243104b --- /dev/null +++ b/lib/app/modules/user_profile/bindings/user_profile_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/user_profile_controller.dart'; + +class UserProfileBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UserProfileController(), + ); + } +} diff --git a/lib/app/modules/user_profile/controllers/user_profile_controller.dart b/lib/app/modules/user_profile/controllers/user_profile_controller.dart new file mode 100644 index 0000000..be6c54f --- /dev/null +++ b/lib/app/modules/user_profile/controllers/user_profile_controller.dart @@ -0,0 +1,253 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:image/image.dart' as img; +// import 'package:image_picker/image_picker.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/upload_user_profile_model.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../views/account_details_view.dart'; +import '../views/profile_details_view.dart'; +import '../views/user_profile_view.dart'; + +class UserProfileController extends GetxController { + final AppRepositories repository = Get.find(); + + static bool isDarkMode = false; + static RxString cmpCustImage = "".obs; + static RxString selectedLocale = "en".obs; + + // ImagePicker imagePicker = ImagePicker(); + + late InputField firstNameField; + late InputField depositAccountField; + // static String? profilePic; + var profilePic = ''.obs; + List listOfTitles = [ + "Personal Details", + "Login Name", + "Mobile Number", + "Email Address", + ]; + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + dp("Drop Down item View==========", item); + } + + @override + void onInit() { + loadProfilePic(); + super.onInit(); + + /// Deposit accounts assign to Drop Down list + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + // dp("=========Desposit All accounts============", depositAccount.toString()); + // allDepositAccounts.add( + // DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + // ); + // } + } + + void uploadUserProfilePicture() async { + if (profilePic == null || profilePic!.isEmpty) { + Toasty.error("Please select an image to upload."); + return; + } + + hideKeyBoard(); + UploadUserProfileModel request = UploadUserProfileModel( + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + porOrgacode: SessionCache.instance.userInfo.porOrgacode, + cmpCustImage: "", + ); + + ServerResponse response = await repository.uploadUserProfilePicture(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + cmpCustImage.value = profilePic.value; + Toasty.success("Profile picture updated successfully."); + } + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + + UserProfileController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, UserProfileController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, Directionality.of(Get.context!) == TextDirection.rtl); + Get.forceAppUpdate(); + update(); + } + + void navigateTo(meuType title) { + if (title == meuType.personalDetails) { + Get.to(const ProfileDetailsView()); + } else if (title == meuType.bankAccountDetails) { + Get.to(() => const AccountDetailsView()); + } else if (title == meuType.inviteFriends) { + // + // Share.share("UCO Digital - Apps on Google Play"); + } else if (title == meuType.changePass) { + Get.toNamed(Routes.changePassword); + } + } + + // void updateProfilePic({required bool fromCamera}) async { + // XFile? imageResult; + // + // if (fromCamera) { + // imageResult = await imagePicker.pickImage(source: ImageSource.camera); + // } else { + // imageResult = await imagePicker.pickImage(source: ImageSource.gallery); + // } + // + // Get.back(); + // + // if (imageResult != null) { + // // Read the image file as bytes + // Uint8List imageBytes = await imageResult.readAsBytes(); + // + // // Check the image size + // // double sizeInMB = imageBytes.length / (1024 * 1024); + // // if (sizeInMB > 1) { + // // Toasty.error("Image is more than 1MB. Please select a smaller image."); + // // return; + // // } + // + // // Decode the image + // img.Image? image = img.decodeImage(imageBytes); + // if (image != null) { + // // Resize the image to reduce its size + // img.Image resizedImage = img.copyResize(image, width: 800); // Adjust the width as needed + // + // // Encode the resized image to base64 + // profilePic.value = base64Encode(img.encodeJpg(resizedImage)); + // + // AppStorage.putString(SessionCache.instance.userInfo.cmpUserId, profilePic.value); + // // uploadUserProfilePicture(); + // update(); + // } else { + // Toasty.error("Failed to decode image."); + // } + // } + // } + // void updateProfilePic({required bool fromCamera}) async { + // XFile? imageResult; + // + // if (fromCamera) { + // imageResult = await imagePicker.pickImage(source: ImageSource.camera); + // } else { + // imageResult = await imagePicker.pickImage(source: ImageSource.gallery); + // } + // + // Get.back(); + // + // if (imageResult != null) { + // // Read the image file as bytes + // Uint8List imageBytes = await imageResult.readAsBytes(); + // + // // Decode the image + // img.Image? image = img.decodeImage(imageBytes); + // if (image != null) { + // // Resize the image to reduce its size + // img.Image resizedImage = img.copyResize(image, width: 800); // Adjust the width as needed + // + // // Encode the resized image to base64 + // profilePic = base64Encode(img.encodeJpg(resizedImage)); + // + // AppStorage.putString("ProfileImage", profilePic!); + // uploadUserProfilePicture(); + // update(); + // } else { + // Toasty.error("Failed to decode image."); + // } + // } + // } + + void removeProfilePic() { + AppStorage.delete(SessionCache.instance.userInfo.cmpUserId); + profilePic.value = ''; + update(); + Get.back(); + } + + void loadProfilePic() async { + // profilePic.value = await AppStorage.getString(SessionCache.instance.userInfo.cmpUserId); + // update(); + String? pic = await AppStorage.getString(SessionCache.instance.userInfo.cmpUserId); + profilePic.value = pic; + } + + void updateName() { + Get.defaultDialog( + title: "Update user name", + contentPadding: const EdgeInsets.only(left: 14, right: 14, bottom: 4), + content: Column( + children: [ + const SizedBox(height: 8), + firstNameField = InputField( + refKey: FormFieldConstants.instance().getFormKey("nameFeils"), + controller: FormFieldConstants.instance().getController("firstNameField"), + hintText: "User Name", + labelText: TranslationKeys.makeTranslation("User Name"), + isTopMarginRequired: false, + showLabel: false, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + CustomButton( + onPressed: () { + if (firstNameField.getCustomText().isEmpty) { + firstNameField.setError("Enter user name"); + return; + } + + var newUserDetails = SessionCache.instance.depositAccountList.first.copyWith(mbmBkmstitle: firstNameField.getCustomText()); + + SessionCache.instance.setDepositAccountList([newUserDetails].obs); + + update(); + + Get.back(); + }, + buttonText: "Update", + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.black), + buttonColor: AppColors.colorSkipBtn, + ) + ], + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/account_details_view.dart b/lib/app/modules/user_profile/views/account_details_view.dart new file mode 100644 index 0000000..35dc15c --- /dev/null +++ b/lib/app/modules/user_profile/views/account_details_view.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:share_plus/share_plus.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/user_profile_controller.dart'; +import 'profile_details_view.dart'; + +class AccountDetailsView extends GetView { + const AccountDetailsView({super.key}); + + @override + Widget build(BuildContext context) { + String className = runtimeType + .toString() + .split('.') + .last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation("Account Detail"), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: Obx(() { + return Column( + children: [ + controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + inputColor: Colors.black, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + const SizedBox(height: 20), + ProfileDetailsTile( + title: 'Personal Details', + subtitle: controller.selectedDepositAccount.value.mbmBkmstitle.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmstitle, + ), + ProfileDetailsTile( + title: 'Account Number', + subtitle: controller.selectedDepositAccount.value.mbmBkmsnumber.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsnumber, + widget: shareButton( + () { + String message = 'Account Number: ${controller.selectedDepositAccount.value.mbmBkmsnumber}'; + String subject = 'Subject for sharing'; + Share.share(message, subject: subject); + }, + ), + ), + ProfileDetailsTile( + title: 'IBAN Number', + subtitle: controller.selectedDepositAccount.value.mbmBkmsnumber.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsnumber, + widget: shareButton( + () { + String message = 'IBAN Number: ${controller.selectedDepositAccount.value.mbmBkmsnumber}'; + String subject = 'Subject for sharing'; + Share.share(message, subject: subject); + }, + ), + ), + ProfileDetailsTile( + title: 'Account Opening Date', + subtitle: controller.selectedDepositAccount.value.mbmBkmsopendate.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsopendate, + ), + ProfileDetailsTile( + title: 'Currency', + subtitle: controller.selectedDepositAccount.value.pcrCurrshort.isEmpty ? "----" :controller.selectedDepositAccount.value.pcrCurrshort, + ), + ], + ); + }), + ), + ), + ); + } + + GestureDetector shareButton(Function()? onTap) { + return GestureDetector( + onTap: onTap, + child: Container( + width: 80, + decoration: BoxDecoration( + color: AppColors.f0f0f0, + border: Border.all( + color: AppColors.c0c0c0, + ), + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.all(4), + child: Row( + children: [ + const SizedBox(width: 12), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textShare), + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox(width: 7), + const Icon(Icons.share, size: 12, color: AppColors.colorPrimary), + const SizedBox(width: 4), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/profile_details_view.dart b/lib/app/modules/user_profile/views/profile_details_view.dart new file mode 100644 index 0000000..315a757 --- /dev/null +++ b/lib/app/modules/user_profile/views/profile_details_view.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/user_profile_controller.dart'; + +class ProfileDetailsView extends GetView { + const ProfileDetailsView({super.key}); + + @override + Widget build(BuildContext context) { + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation("Profile"), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: GetBuilder(builder: (controller) { + return Column( + children: [ + const SizedBox(height: 5), + ProfileDetailsTile( + title: 'Personal Details', + subtitle: '' + // SessionCache.instance.depositAccountList.first.mbmBkmstitle, + ), + ProfileDetailsTile( + title: 'Login Name', + subtitle: '' + // SessionCache.instance.userInfo.name, + ), + ProfileDetailsTile( + title: 'Mobile Number', + subtitle: '' + // SessionCache.instance.depositAccountList.first.padAdrsmobphone, + ), + ProfileDetailsTile( + title: 'Email Address', + subtitle: '' + // SessionCache.instance.userInfo.cmpUserId, + ), + ], + ); + }), + ), + ), + ); + } + + Widget editButton(BuildContext context, {void Function()? onTap}) { + return GestureDetector( + onTap: onTap, + child: Container( + width: 65, + decoration: BoxDecoration( + color: AppColors.f0f0f0, + border: Border.all( + color: AppColors.c0c0c0, + ), + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.all(4), + child: Row( + children: [ + const SizedBox( + width: 10, + ), + Text( + "Edit", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox( + width: 7, + ), + const Icon( + Icons.edit, + size: 12, + color: AppColors.colorPrimary, + ), + const SizedBox( + width: 2, + ), + ], + ), + ), + ); + } +} + +class ProfileDetailsTile extends StatelessWidget { + const ProfileDetailsTile({ + super.key, + required this.title, + required this.subtitle, + this.widget, + }); + + final String title; + final String subtitle; + final Widget? widget; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border.all( + color: AppColors.colorGrey350, + ), + borderRadius: BorderRadius.circular(8)), + height: widget == null ? 60 : 91, + width: Get.width, + padding: const EdgeInsets.only(left: 12, right: 14, top: 12), + margin: const EdgeInsets.only(top: 14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 10, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 4), + // Text( + // // subtitle, + // style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w400), + // ), + const SizedBox(height: 8), + widget ?? const SizedBox(), + widget == null + ? const SizedBox() + : const SizedBox( + height: 8, + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/user_profile_view.dart b/lib/app/modules/user_profile/views/user_profile_view.dart new file mode 100644 index 0000000..93c8ddf --- /dev/null +++ b/lib/app/modules/user_profile/views/user_profile_view.dart @@ -0,0 +1,269 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/user_profile_controller.dart'; + +enum meuType { personalDetails, bankAccountDetails, inviteFriends, changePass } + +var menuList = [ + {"title": "Personal Details", "icons": AppAssets.ic_manage_account, "type": meuType.personalDetails}, + {"title": "Bank Account Details", "icons": AppAssets.bankDetails, "type": meuType.bankAccountDetails}, + {"title": "Invite Friends to UCO Digital", "icons": AppAssets.inviteFriendsUco, "type": meuType.inviteFriends}, + {"title": "Change Password", "icons": AppAssets.changePassoword, "type": meuType.changePass}, +]; + +class UserProfileView extends GetView { + const UserProfileView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var name; + + try { + name = SessionCache.instance.userInfo.name.substring(0, 1); + } catch (e) { + name = "SA"; + } + + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textMyProfile), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: GetBuilder(builder: (controller) { + return Column( + children: [ + const SizedBox(height: 20), + Align( + alignment: Alignment.center, + child: Card( + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + child: Container( + width: 130, + height: 130, + margin: const EdgeInsets.all(12), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey900), + borderRadius: BorderRadius.circular(120), + image: (controller.profilePic?.isEmpty ?? true) + ? null + : DecorationImage( + image: MemoryImage( + base64Decode(controller.profilePic.value), + ), + fit: BoxFit.cover)), + child: Stack( + clipBehavior: Clip.none, + children: [ + (controller.profilePic?.isEmpty ?? true) ? Center(child: Text(name)) : const Center(), + Positioned( + bottom: -17, + left: 130 / 2 - 14, + child: GestureDetector( + onTap: () { + showProfileUpdateSheet(); + }, + child: Container( + width: 35, + height: 35, + decoration: BoxDecoration(color: AppColors.white, borderRadius: BorderRadius.circular(120)), + child: const Icon( + Icons.camera_alt_outlined, + color: AppColors.colorPrimary, + size: 18, + ), + ), + )) + ], + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + // const + ...menuList + .map((Map e) => ProfileMenuTile( + iconPath: e["icons"]!!, + onTap: (title) { + dp("Menu", e["type"]); + controller.navigateTo(e["type"]); + }, + title: e["title"]!, + )) + .toList() + ], + ); + }), + ), + ), + ); + } +} + +class ProfileMenuTile extends StatelessWidget { + const ProfileMenuTile({ + super.key, + required this.iconPath, + required this.title, + required this.onTap, + }); + + final String iconPath; + final String title; + final Function(String) onTap; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + onTap: () { + onTap(title); + }, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: SvgPicture.asset( + iconPath, + height: 30, + width: 30, + ), + ), + ), + Text( + title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(16.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey700)) + ], + ), + ), + ), + ); + } +} + +showProfileUpdateSheet() { + Get.bottomSheet( + responsiveWidget( + GetBuilder(builder: (controller) { + return Stack( + fit: StackFit.loose, + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.only(left: 20, right: 30, top: 20, bottom: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Spacer(), + InkWell( + onTap: () { + Navigator.pop(Get.context!); + }, + child: SvgPicture.asset(AppAssets.ic_cross, width: 15, height: 15), + ), + ], + ), + const CircleAvatar( + radius: 16, + backgroundColor: AppColors.colorGrey300, + child: Icon(Icons.camera_alt_outlined, color: AppColors.colorPrimary, size: 15), + ), + const SizedBox(height: 20), + SizedBox( + width: 150, + child: Text( + "Change \nProfile Picture", + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 16, fontWeight: FontWeight.w400, color: AppColors.black, height: 2), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + btnTileB("Choose From Photos", () { + dp("", ""); + // controller.updateProfilePic(fromCamera: false); + }), + btnTileB("Take a photo", () { + dp("", ""); + // controller.updateProfilePic(fromCamera: true); + }), + btnTileB("Remove Profile Picture", () { + dp("", ""); + controller.removeProfilePic(); + }, color: Colors.red, textColor: AppColors.white), + ], + ), + ), + ), + ], + ); + }), + ), + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} + +Widget btnTileB(String title, Function() onTap, {Color color = AppColors.E5E9F2, Color textColor = AppColors.c212121}) { + return GestureDetector( + onTap: onTap, + child: SizedBox( + height: 45, + width: Get.width, + child: Card( + elevation: 0.0, + color: color, + child: Center( + child: Text( + title, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400, color: textColor), + )), + ), + ), + ); +} diff --git a/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart b/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart new file mode 100644 index 0000000..4fd2484 --- /dev/null +++ b/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_payment_controller.dart'; + +class UtilityBillsPaymentBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsPaymentController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart b/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart new file mode 100644 index 0000000..7f4f2bd --- /dev/null +++ b/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class UtilityBillsPaymentController extends GetxController { + //TODO: Implement UtilityBillsPaymentController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart b/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart new file mode 100644 index 0000000..14c3087 --- /dev/null +++ b/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart @@ -0,0 +1,370 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_payment_controller.dart'; + +class UtilityBillsPaymentView extends GetView { + const UtilityBillsPaymentView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPTCLLandLine), + style: Theme.of(context).textTheme.titleSmall)), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectAccountDetails), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 10.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textCreditCard), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + const Icon(Icons.keyboard_arrow_down_sharp, + color: AppColors.colorText), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 10.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textCreditCardNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + const Icon(Icons.credit_card_rounded, + color: AppColors.colorText), + ], + ), + ), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textAmountDebit), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 13, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textEnterConsumerName), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textTotalAmount), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 13, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textEnterAmount), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetails), + style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillConsumerName), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textAmountDueAfterDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillStatus), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textTotalAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 50), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailUnPaid), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + ], + ), + ], + ), + CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textPayNow), + buttonPadding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart b/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart new file mode 100644 index 0000000..16cb75e --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_selected_category_controller.dart'; + +class UtilityBillsSelectedCategoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsSelectedCategoryController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart b/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart new file mode 100644 index 0000000..affb675 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../bill_management/views/bill_management_view.dart'; + +class UtilityBillsSelectedCategoryController extends GetxController { + + BillType? selectedBillType = Get.arguments; + late String description; + late AssetImage image; + + @override + void onReady() { + super.onReady(); + description = Get.arguments[1]; + image = Get.arguments[2]; + } +} diff --git a/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart b/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart new file mode 100644 index 0000000..0f975b0 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_selected_category_controller.dart'; + +class UtilityBillsSelectedCategoryView extends GetView { + const UtilityBillsSelectedCategoryView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var args = Get.arguments; + + var icon = args["icon"]; + + var type = args["billTypes"]; + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Column( + children: [ + Stack( + children: [ + Container(height: 50, decoration: BoxDecoration(color: AppColors.colorPrimary.withOpacity(0.98), borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(40)))), + Column(children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset(AppAssets.ic_government), + )), + Expanded( + flex: 4, + child: Padding( + padding: const EdgeInsets.only(left: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity), + style: Theme.of(context).textTheme.titleSmall, + ), + const SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(type), + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ), + )), + Expanded(flex: 1, child: SvgPicture.asset(icon)), + ], + )), + ), + ), + // Align( + // alignment: AppSettingController.isRTL.value + // ? Alignment.centerRight + // : Alignment.centerLeft, + // child: Padding( + // padding: + // EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: Text( + // TranslationKeys.makeTranslation( + // TranslationKeys.textEnterConsumerName), + // style: Theme.of(context).textTheme.titleSmall), + // )), + Container( + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterConsumerName), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS, + ); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ), + ]) + ], + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart b/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart new file mode 100644 index 0000000..09d9a4d --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_selected_category_details_controller.dart'; + +class UtilityBillsSelectedCategoryDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsSelectedCategoryDetailsController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart b/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart new file mode 100644 index 0000000..926e9a7 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class UtilityBillsSelectedCategoryDetailsController extends GetxController { + //TODO: Implement UtilityBillsSelectedCategoryDetailsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart b/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart new file mode 100644 index 0000000..3903f9b --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_selected_category_details_controller.dart'; + +class UtilityBillsSelectedCategoryDetailsView extends GetView { + const UtilityBillsSelectedCategoryDetailsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed(Routes.UTILITY_BILLS_PAYMENT); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ), + ], + body: SingleChildScrollView( + child: Stack( + children: [ + Container(height: 120, decoration: BoxDecoration(color: AppColors.colorPrimary.withOpacity(0.98), borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(40)))), + Stack( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), + elevation: 5.0, + child: Container( + // height: 360, + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 25), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + children: [ + const SizedBox(height: 15), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailContent), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 15), + Container( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 75), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: AppColors.colorGrey350, width: 1.0)), + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBalance), + style: Theme.of(context).textTheme.titleSmall!.copyWith(color: AppColors.colorText), + )), + const SizedBox(height: 15), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailCustomerName), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAmount), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillDueDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAmountDue), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAfterDueDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillStatus), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ], + ), + const SizedBox(width: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailUnPaid), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 25.0), + child: Image.asset(AppAssets.ic_government), + ), + ], + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/res/app_colors.dart b/lib/app/res/app_colors.dart new file mode 100644 index 0000000..4c544ff --- /dev/null +++ b/lib/app/res/app_colors.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class AppColors { + static const colorPrimary = Color(0xfff5831f); + static const colorPrimaryLight = Color(0xffffdcac); + static const colorPrimaryDark = Color(0xffbb5f0f); + + static const colorSecondary = Color(0xffffffff); + static const colorTitle = Color(0xff5A5A5A); + static const colorText = Color(0xff7a7a7a); + + static const colorButton = Color(0xff30a240); + static const colorSpamText = Color(0xfff69b4b); + static const colorDialogBG = Color(0xffe2791d); + static const colorDialog = Color(0xffffd7d2); + + // Generals + static const white = Colors.white; + static const yellow = Colors.yellow; + static const black = Colors.black; + static const red = Colors.red; + static const transparent = Colors.transparent; + + // Gray and black + static const Color colorGrey50 = Color(0xFFF8FAFC); + static const Color colorGrey100 = Color(0xFFF5F5F5); + static const Color colorGrey200 = Color(0xFFEEEEEE); + static const Color colorGrey300 = Color(0xFFE0E0E0); + static const Color colorGrey350 = Color(0xFFD6D6D6); + static const Color colorGrey400 = Color(0xFFBDBDBD); + static const Color colorGrey500 = Color(0xFF9E9E9E); + static const Color colorGrey600 = Color(0xFF757575); + static const Color colorGrey700 = Color(0xFF616161); + static const Color colorGrey800 = Color(0xFF424242); + static const Color colorGrey850 = Color(0xFF333333); + static const Color colorGrey900 = Color(0xFF212121); + + static const Color colorNavyBlue = Color(0xFF1C274C); + static const titleColor = colorGrey700; + + /// General + static const colorSkipBtn = Color(0xFFf3e7bc); + static const colorBorderSkipBtn = Color(0xFFB79D3E); + + static const toolbarBackgroundColor = Color(0xFF1565a6); + + static var minusColor = Colors.red; + // Input Text + static const hintColor = colorPrimary; + static const inputErrorColor = Colors.red; + static const inputTextColor = colorPrimary; + static const inputLabelColor = colorPrimary; + static const colorFontPrimary = black; + static const colorFontSecondary = Color(0xFF344054); + static const c0c0c0 = Color(0xFFC0C0C0); + static const f0f0f0 = Color(0xFFF0F0F0); + + static const E5E9F2 = Color(0xFFE5E9F2); + + static const c212121 = Color(0xff212121); + static const c878787 = Color(0xff878787); + static const ff444444 = Color(0xff444444); + static const ffF95846 = Color(0xffF95846); + + static var CFCFCF = Color(0xffCFCFCF); + + static var F0F0D = Color(0xff0F0F0D); + static const colorRed = Color(0xffff0000); + static const FDF7F1 = Color(0xffFDF7F1); + + +} diff --git a/lib/app/res/app_dimensions.dart b/lib/app/res/app_dimensions.dart new file mode 100644 index 0000000..27262b9 --- /dev/null +++ b/lib/app/res/app_dimensions.dart @@ -0,0 +1,14 @@ +class AppDimensions { + static double screenHorizontalPadding = 20; + static double screenVerticalPadding = 20; + static double radiusBottomSheet = 20; + static double radiusButton = 50; + static double radiusCard = 10; + static double elevation = 5.0; + + // Input + static double inputRadius = 20; + + // Text + static double customTextSize = 12; +} diff --git a/lib/app/res/app_theme.dart b/lib/app/res/app_theme.dart new file mode 100644 index 0000000..36914fa --- /dev/null +++ b/lib/app/res/app_theme.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'app_colors.dart'; +import 'app_dimensions.dart'; + +/// Created by Waqas Khurshid on 12/09/2023. +class AppThemeData { + // input field + static const inputLabelColor = AppColors.colorGrey700; + static const inputTextColor = AppColors.colorGrey700; + static const inputBackgroundColor = AppColors.colorGrey700; + static const inputHintColor = AppColors.colorGrey500; + static const inputBorderColor = AppColors.colorGrey500; + static const inputFocusedBorderColor = AppColors.colorGrey500; + static const inputDisabledBorderColor = AppColors.colorGrey300; + static const inputEnabledBorderColor = AppColors.colorGrey500; + static const inputErrorBackgroundColor = AppColors.transparent; + static const inputErrorBorderColor = AppColors.red; + static const inputErrorColor = AppColors.red; + + static BorderRadius borderRadius = const BorderRadius.all(Radius.circular(50.0)); + static const TextStyle labelStyle = TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: inputLabelColor); + static const TextStyle inputStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: inputTextColor); + static const TextStyle hintStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: inputHintColor); + static TextStyle errorStyle = const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: inputErrorColor); + + // *************** button ****************** + static double buttonRadius = 50; + static double buttonHorizontlePadding = 10; + static double buttonVerticalPadding = 10; + static const Color buttonBackgroundColor = AppColors.colorButton; + static final OutlinedBorder buttonBorder = RoundedRectangleBorder(borderRadius: BorderRadius.circular(buttonRadius)); + static const TextStyle buttonTextStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.white); + +// *************** App Bar ****************** + static const TextStyle appBarTextStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: 14, color: AppColors.white); + +// *************** CustomText ****************** + static const textFieldsColor = AppColors.colorGrey700; + static final TextStyle textFieldStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: AppDimensions.customTextSize, color: textFieldsColor); +} + +ThemeData appTheme() { + return ThemeData( + useMaterial3: false, + fontFamily: 'Roboto', + + /// AppBar Theme + appBarTheme: AppBarTheme( + //color: AppColors.appBar, + centerTitle: true, + backgroundColor: AppColors.colorPrimary, + elevation: AppDimensions.elevation, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: AppColors.colorPrimary, + ), + titleTextStyle: const TextStyle(fontWeight: FontWeight.w700, fontSize: 14, color: AppColors.colorTitle), + iconTheme: const IconThemeData(color: AppColors.colorSecondary), + ), + + /// Floating Action Button Design + floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: Colors.transparent), + + /// Titles And Text Theme + textTheme: const TextTheme( + ///Display Large Style + displayLarge: TextStyle(fontSize: 23, fontWeight: FontWeight.w500, color: AppColors.colorTitle), + displayMedium: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + displaySmall: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.colorText), + + /// Display Titles Style + titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + titleMedium: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + titleSmall: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.colorTitle), + + /// Display Body Style + bodyLarge: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + bodyMedium: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + bodySmall: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorText), + + /// Display Label Style + labelLarge: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + labelMedium: TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: AppColors.colorText), + labelSmall: TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + + /// Dialog Theme + dialogTheme: const DialogThemeData(shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 5.0, backgroundColor: AppColors.colorSecondary), + + /// Card Theme + cardTheme: CardThemeData( + color: AppColors.colorGrey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + ), + elevation: AppDimensions.elevation, + ), + + /// Input Decoration Theme + inputDecorationTheme: InputDecorationTheme( + isDense: true, + // Reduces the overall height of the TextFormField + errorMaxLines: 1, + // Limits the error message to one line + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + border: const OutlineInputBorder( + borderSide: BorderSide(color: AppColors.transparent), + ), + errorStyle: GoogleFonts.inter( + textStyle: const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.colorPrimary), + ), + disabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + errorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + labelStyle: GoogleFonts.inter( + textStyle: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: AppColors.colorText, + ), + ), + hintStyle: GoogleFonts.inter( + textStyle: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: AppColors.colorText, + ), + ), + iconColor: AppColors.colorButton), + + /// Divider Theme + dividerTheme: const DividerThemeData( + color: Colors.transparent, + ), + + /// Elevated Button Theme + elevatedButtonTheme: ElevatedButtonThemeData( + style: ButtonStyle( + minimumSize: MaterialStateProperty.all(Size(AppDimensions.screenVerticalPadding, AppDimensions.screenVerticalPadding)), + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.pressed)) { + return Colors.white54; + } else if (states.contains(MaterialState.disabled)) { + return Colors.white70; + } + return Colors.white70; + }, + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + //side: BorderSide(color: borderColor ?? Colors.transparent), + ), + ), + ), + ), + + /// CheckBox Theme + checkboxTheme: CheckboxThemeData( + checkColor: MaterialStateProperty.all(AppColors.colorButton), + fillColor: MaterialStateProperty.all(AppColors.colorButton), + //splashRadius: 10, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppDimensions.radiusCard)), + visualDensity: VisualDensity.compact, + side: BorderSide( + color: AppColors.colorButton, + width: AppDimensions.radiusCard, + style: BorderStyle.solid, + // strokeAlign: StrokeAlign.center) + ), + ), + dropdownMenuTheme: const DropdownMenuThemeData(inputDecorationTheme: InputDecorationTheme())); +} + +/// check is TabletDevice or Mobile +/// if Device is Tablet Resolution then this occur otherwise mobile Resolution occur +bool isTabletDevice(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + double screenHeight = MediaQuery.of(context).size.height; + + /// Define a threshold size to consider as a tablet + double tabletThreshold = 600.0; + + return screenWidth > tabletThreshold && screenHeight > tabletThreshold; +} + +// dynamic isDarkMode() async { +// return await AppStorage.getBoolean(AppConstants.IS_DARK_MODE, fallback: false); +// } diff --git a/lib/app/res/suppoted_languages.dart b/lib/app/res/suppoted_languages.dart new file mode 100644 index 0000000..214b4d1 --- /dev/null +++ b/lib/app/res/suppoted_languages.dart @@ -0,0 +1,13 @@ +import 'package:get/get_navigation/src/root/internacionalization.dart'; + +import '../l10n/Arabic.dart'; +import '../l10n/English.dart'; + + +class SupportedLanguages extends Translations { + @override + Map> get keys => { + ...English().keys, + ...Arabic().keys, + }; +} diff --git a/lib/app/routes/app_pages.dart b/lib/app/routes/app_pages.dart new file mode 100644 index 0000000..7359bd6 --- /dev/null +++ b/lib/app/routes/app_pages.dart @@ -0,0 +1,507 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:responsive_framework/responsive_framework.dart' as r; + +import '../modules/about_us/bindings/about_us_binding.dart'; +import '../modules/about_us/views/about_us_view.dart'; +import '../modules/account_statement/bindings/account_statement_binding.dart'; +import '../modules/account_statement/views/account_statement_view.dart'; +import '../modules/add_money/bindings/add_money_binding.dart'; +import '../modules/add_money/bindings/add_money_otp_binding.dart'; +import '../modules/add_money/bindings/payment_method_binding.dart'; +import '../modules/add_money/views/add_money_view.dart'; +import '../modules/add_money/views/shared/currency_list_screen.dart'; +import '../modules/add_money/views/shared/otp_add_money.dart'; +import '../modules/add_money/views/shared/payment_method_view.dart'; +import '../modules/add_new_account/bindings/add_new_binding.dart'; +import '../modules/add_new_account/views/add_new_account_view.dart'; +import '../modules/agent_location/bindings/agent_location_binding.dart'; +import '../modules/agent_location/views/agent_location_view.dart'; +import '../modules/app_intro/bindings/intro_screen_binding.dart'; +import '../modules/app_intro/views/intro_screen_view.dart'; +import '../modules/app_setting/bindings/app_setting_binding.dart'; +import '../modules/app_setting/views/app_setting_view.dart'; +import '../modules/beneficiary_management/bindings/beneficiary_management_binding.dart'; +import '../modules/beneficiary_management/views/beneficiary_management_view.dart'; +import '../modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart'; +import '../modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart'; +import '../modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart'; +import '../modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart'; +import '../modules/bill_management/bindings/bill_management_binding.dart'; +import '../modules/bill_management/views/bill_management_view.dart'; +import '../modules/bill_management_category/bindings/bill_management_category_binding.dart'; +import '../modules/bill_management_category/views/bill_management_category_view.dart'; +import '../modules/career/bindings/career_binding.dart'; +import '../modules/career/views/career_view.dart'; +import '../modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart'; +import '../modules/change_transaction_pin/views/change_transaction_pin_view.dart'; + +// import '../modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart'; +// import '../modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart'; +import '../modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart'; +import '../modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart'; +import '../modules/cheque_activation/bindings/cheque_activation_binding.dart'; +import '../modules/cheque_activation/views/cheque_activation_view.dart'; +import '../modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart'; +import '../modules/cheque_book_request_details/views/cheque_book_request_details_view.dart'; +import '../modules/cheque_deposit/bindings/cheque_deposit_binding.dart'; +import '../modules/cheque_deposit/views/cheque_deposit_view.dart'; +import '../modules/cheque_management/bindings/cheque_management_binding.dart'; +import '../modules/cheque_management/views/cheque_management_view.dart'; +import '../modules/cheque_request/bindings/cheque_request_binding.dart'; +import '../modules/cheque_request/views/cheque_request_view.dart'; +import '../modules/cheque_status/bindings/cheque_status_binding.dart'; +import '../modules/cheque_status/views/cheque_status_view.dart'; +import '../modules/cheque_status_history/bindings/cheque_status_history_binding.dart'; +import '../modules/cheque_status_history/views/cheque_status_history_view.dart'; +import '../modules/contacts_screen/bindings/contacts_screen_binding.dart'; +import '../modules/contacts_screen/views/contacts_screen_view.dart'; +import '../modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart'; +import '../modules/create_transaction_pin/views/create_transaction_pin_view.dart'; +import '../modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart'; +import '../modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart'; +import '../modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart'; +import '../modules/dail_transaction_limit/views/dail_transaction_limit_view.dart'; +import '../modules/dashboard/bindings/dashboard_screen_binding.dart'; +import '../modules/dashboard/views/dashboard_screen_view.dart'; +import '../modules/faqs/bindings/faqs_binding.dart'; +import '../modules/faqs/bindings/faqs_first_screen_binding.dart'; +import '../modules/faqs/bindings/faqs_second_screen_binding.dart'; +import '../modules/faqs/bindings/faqs_third_screen_binding.dart'; +import '../modules/faqs/views/faqs_first_screen_view.dart'; +import '../modules/faqs/views/faqs_second_screen_view.dart'; +import '../modules/faqs/views/faqs_third_screen_view.dart'; +import '../modules/faqs/views/faqs_view.dart'; +import '../modules/general_ledger/bindings/general_ledger_binding.dart'; +import '../modules/general_ledger/views/general_ledger_view.dart'; +import '../modules/internal_account_transaction/bindings/internal_transaction_binding.dart'; +import '../modules/internal_account_transaction/views/internal_transaction_view.dart'; +import '../modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart'; +import '../modules/internal_transaction_otp/views/internal_transaction_otp_view.dart'; +import '../modules/login/bindings/login_screen_binding.dart'; +import '../modules/login/views/login_screen_view.dart'; +import '../modules/login_otp/bindings/o_t_p_screen_binding.dart'; +import '../modules/login_otp/views/o_t_p_screen_view.dart'; +import '../modules/my_account/bindings/my_account_binding.dart'; +import '../modules/my_account/views/my_account_view.dart'; +import '../modules/new_beneficiary/bindings/new_beneficiary_binding.dart'; +import '../modules/new_beneficiary/views/new_beneficiary_view.dart'; +import '../modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart'; +import '../modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart'; +import '../modules/notifications/bindings/notifications_binding.dart'; +import '../modules/notifications/views/notifications_view.dart'; +import '../modules/password_change/bindings/password_change_binding.dart'; +import '../modules/password_change/views/password_change_view.dart'; +import '../modules/privacy_policy/bindings/privacy_policy_binding.dart'; +import '../modules/privacy_policy/views/privacy_policy_view.dart'; +import '../modules/qr_setting/bindings/qr_setting_binding.dart'; +import '../modules/qr_setting/views/qr_scan_screen.dart'; +import '../modules/qr_setting/views/qr_setting_view.dart'; +import '../modules/qr_setting/views/qr_view_screen.dart'; +import '../modules/recipient_details/bindings/recipient_details_binding.dart'; +import '../modules/recipient_details/views/recipient_details_view.dart'; +import '../modules/sample_fields/bindings/sample_fields_binding.dart'; +import '../modules/sample_fields/views/sample_fields_view.dart'; +import '../modules/sign_up/bindings/sign_up_screen_otp_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step1_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step2_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step3_binding.dart'; +import '../modules/sign_up/views/sign_up_screen_otp_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step1_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step2_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step3_view.dart'; +import '../modules/splash/bindings/splash_screen_binding.dart'; +import '../modules/splash/views/splash_screen_view.dart'; +import '../modules/transaction_history/bindings/transaction_history_binding.dart'; +import '../modules/transaction_history/views/transaction_history_view.dart'; +import '../modules/u_received/bindings/u_received_binding.dart'; +import '../modules/u_received/views/u_received_view.dart'; +import '../modules/u_send/bindings/u_send_binding.dart'; +import '../modules/u_send/views/u_send_view.dart'; +import '../modules/u_send_otp/bindings/u_send_otp_binding.dart'; +import '../modules/u_send_otp/views/u_send_otp_view.dart'; +import '../modules/user_activity/bindings/user_activity_binding.dart'; +import '../modules/user_activity/views/user_activity_view.dart'; +import '../modules/user_profile/bindings/user_profile_binding.dart'; +import '../modules/user_profile/views/user_profile_view.dart'; +import '../modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart'; +import '../modules/utility_bills_payment/views/utility_bills_payment_view.dart'; +import '../modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart'; +import '../modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart'; +import '../modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart'; +import '../modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart'; + +part 'app_routes.dart'; + +class AppPages { + AppPages._(); + + static String INITIAL = Routes.SPLASH_SCREEN; + + static final routes = [ + GetPage( + name: _Paths.SPLASH_SCREEN, + page: () => responsiveWidget(const SplashScreenView()), + binding: SplashScreenBinding(), + ), + GetPage( + name: _Paths.INTRO_SCREEN, + page: () => responsiveWidget(IntroScreenView()), + binding: IntroScreenBinding(), + ), + GetPage( + name: _Paths.LOGIN_SCREEN, + page: () => responsiveWidget(const LoginScreenView()), + binding: LoginScreenBinding(), + ), + GetPage( + name: _Paths.DASHBOARD_SCREEN, + page: () => responsiveWidget(const DashboardScreenView()), + binding: DashboardScreenBinding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP1, + page: () => responsiveWidget(const SignUpScreenStep1View()), + binding: SignUpScreenStep1Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP2, + page: () => responsiveWidget(const SignUpScreenStep2View()), + binding: SignUpScreenStep2Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP3, + page: () => responsiveWidget(const SignUpScreenStep3View()), + binding: SignUpScreenStep3Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_OTP, + page: () => responsiveWidget(const SignUpScreenOTPView()), + binding: SignUpScreenOTPBinding(), + ), + GetPage( + name: _Paths.O_T_P_SCREEN, + page: () => responsiveWidget(const OTPScreenView()), + binding: OTPScreenBinding(), + ), + GetPage( + name: _Paths.MY_ACCOUNT, + page: () => responsiveWidget(const MyAccountView()), + binding: MyAccountBinding(), + ), + GetPage( + name: _Paths.BILL_MANAGEMENT, + page: () => responsiveWidget(const BillManagementView()), + binding: BillManagementBinding(), + ), + GetPage( + name: _Paths.CHEQUE_MANAGEMENT, + page: () => responsiveWidget(const ChequeManagementView()), + binding: ChequeManagementBinding(), + ), + GetPage( + name: _Paths.U_SEND, + page: () => responsiveWidget(const USendView()), + binding: USendBinding(), + ), + GetPage( + name: _Paths.INTERNAL_ACCOUNT_TRANS, + page: () => responsiveWidget(const InternalAccountTransView()), + binding: InternalAccountTransBinding(), + ), + GetPage( + name: _Paths.U_RECEIVED, + page: () => responsiveWidget(const UReceivedView()), + binding: UReceivedBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_MANAGEMENT, + page: () => responsiveWidget(const BeneficiaryManagementView()), + binding: BeneficiaryManagementBinding(), + ), + GetPage( + name: _Paths.NEW_BENEFICIARY, + page: () => responsiveWidget(const NewBeneficiaryView()), + binding: NewBeneficiaryBinding(), + ), + GetPage( + name: _Paths.NEW_BENEFICIARY_OPT, + page: () => responsiveWidget(const NewBeneficiaryOtpView()), + binding: NewBeneficiaryOtpBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_TRANSFER_MONEY, + page: () => responsiveWidget(const BeneficiaryTransferView()), + binding: BeneficiaryTransferBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_TRANSFER_MONEY_OTP, + page: () => responsiveWidget(const BeneficiaryTransferOtpView()), + binding: BeneficiaryTransferOtpBinding(), + ), + // GetPage( + // name: _Paths.AGENT_LOCATION, + // page: () => responsiveWidget(const AgentLocationView()), + // binding: AgentLocationBinding(), + // ), + GetPage( + name: _Paths.ACCOUNT_STATEMENT, + page: () => responsiveWidget(const AccountStatementView()), + binding: AccountStatementBinding(), + ), + GetPage( + name: _Paths.USER_PROFILE, + page: () => responsiveWidget(const UserProfileView()), + binding: UserProfileBinding(), + ), + GetPage( + name: _Paths.PRIVACY_POLICY, + page: () => responsiveWidget(const PrivacyPolicyView()), + binding: PrivacyPolicyBinding(), + ), + GetPage( + name: _Paths.USER_ACTIVITY, + page: () => responsiveWidget(const UserActivityView()), + binding: UserActivityBinding(), + ), + GetPage( + name: _Paths.TRANSACTION_HISTORY, + page: () => responsiveWidget(const TransactionHistoryView()), + binding: TransactionHistoryBinding(), + ), + GetPage( + name: _Paths.ABOUT_US, + page: () => responsiveWidget(const AboutUsView()), + binding: AboutUsBinding(), + ), + GetPage( + name: _Paths.CAREER, + page: () => responsiveWidget(const CareerView()), + binding: CareerBinding(), + ), + // GetPage( + // name: _Paths.CONTACTS_SCREEN, + // page: () => responsiveWidget(const ContactsScreenView()), + // binding: ContactsScreenBinding(), + // ), + GetPage( + name: _Paths.RECIPIENT_DETAILS, + page: () => responsiveWidget(const RecipientDetailsView()), + binding: RecipientDetailsBinding(), + ), + GetPage( + name: _Paths.U_SEND_OTP, + page: () => responsiveWidget(const USendOtpView()), + binding: USendOtpBinding(), + ), + GetPage( + name: _Paths.SAMPLE_FIELDS, + page: () => responsiveWidget(const SampleFieldsView()), + binding: SampleFieldsBinding(), + ), + GetPage( + name: _Paths.INTRO_SCREEN, + page: () => responsiveWidget(IntroScreenView()), + binding: IntroScreenBinding(), + ), + GetPage( + name: _Paths.changePassword, + page: () => responsiveWidget(const ChangePasswordScreen()), + binding: ChangePasswordBindings(), + ), + GetPage( + name: _Paths.faqsView, + page: () => responsiveWidget(FaqsView()), + binding: FaqsBinding(), + ), + GetPage( + name: _Paths.BILL_MANAGEMENT_CATEGORY, + page: () => responsiveWidget(const BillManagementCategoryView()), + binding: BillManagementCategoryBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_PAYMENT, + page: () => responsiveWidget(const UtilityBillsPaymentView()), + binding: UtilityBillsPaymentBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_SELECTED_CATEGORY, + page: () => responsiveWidget(const UtilityBillsSelectedCategoryView()), + binding: UtilityBillsSelectedCategoryBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS, + page: () => responsiveWidget(const UtilityBillsSelectedCategoryDetailsView()), + binding: UtilityBillsSelectedCategoryDetailsBinding(), + ), + GetPage( + name: _Paths.CHEQUE_ACTIVATION, + page: () => responsiveWidget(const ChequeActivationView()), + binding: ChequeActivationBinding(), + ), + GetPage( + name: _Paths.CHEQUE_BOOK_REQUEST_DETAILS, + page: () => responsiveWidget(const ChequeBookRequestDetailsView()), + binding: ChequeBookRequestDetailsBinding(), + ), + GetPage( + name: _Paths.CHEQUE_DEPOSIT, + page: () => responsiveWidget(const ChequeDepositView()), + binding: ChequeDepositBinding(), + ), + GetPage( + name: _Paths.CHEQUE_REQUEST, + page: () => responsiveWidget(const ChequeRequestView()), + binding: ChequeRequestBinding(), + ), + GetPage( + name: _Paths.CHEQUE_STATUS, + page: () => responsiveWidget(const ChequeStatusView()), + binding: ChequeStatusBinding(), + ), + GetPage( + name: _Paths.CHEQUE_STATUS_HISTORY, + page: () => responsiveWidget(const ChequeStatusHistoryView()), + binding: ChequeStatusHistoryBinding(), + ), + GetPage( + name: _Paths.APP_SETTING, + page: () => responsiveWidget(const AppSettingView()), + binding: AppSettingBinding(), + ), + GetPage( + name: _Paths.DAIL_TRANSACTION_LIMIT, + page: () => responsiveWidget(const DailTransactionLimitView()), + binding: DailTransactionLimitBinding(), + ), + GetPage( + name: _Paths.CHANGE_TRANSACTION_PIN, + page: () => responsiveWidget(const ChangeTransactionPinView()), + binding: ChangeTransactionPinBinding(), + ), + // GetPage( + // name: _Paths.CHANGE_TRANSACTION_PIN_OTP, + // page: () => responsiveWidget(const ChangeTransactionPinOtpView()), + // binding: ChangeTransactionPinOtpBinding(), + // ), + // GetPage( + // name: _Paths.QR_SETTING, + // page: () => responsiveWidget(const QrSettingView()), + // binding: QrSettingBinding(), + // ), + GetPage( + name: _Paths.NOTIFICATIONS, + page: () => responsiveWidget(const NotificationsView()), + binding: NotificationsBinding(), + ), + GetPage( + name: _Paths.CREATE_TRANSACTION_PIN, + page: () => responsiveWidget(const CreateTransactionPinView()), + binding: CreateTransactionPinBinding(), + ), + GetPage( + name: _Paths.CREATE_TRANSACTION_PIN_OTP, + page: () => responsiveWidget(const CreateTransactionPinOtpView()), + binding: CreateTransactionPinOtpBinding(), + ), + GetPage( + name: _Paths.qrViewScreen, + page: () => responsiveWidget(const QrViewScreen()), + ), + // GetPage( + // name: _Paths.qrScanView, + // page: () => responsiveWidget(const QrScanScreen()), + // binding: QrSettingBinding(), + // ), + GetPage( + name: _Paths.GENERAL_LEDGER, + page: () => responsiveWidget(const GeneralLedgerView()), + binding: GeneralLedgerBinding(), + ), + GetPage( + name: _Paths.PAYMENT_METHOD, + page: () => responsiveWidget(const PaymentMethodView()), + binding: PaymentMethodBinding(), + ), + GetPage( + name: _Paths.ADD_MONEY, + page: () => responsiveWidget(const AddMoneyView()), + binding: AddMoneyBinding(), + ), + GetPage( + name: _Paths.OTP_ADD_MONEY, + page: () => responsiveWidget(const AddMoneyOTPView()), + binding: AddMoneyOTPBinding(), + ), + GetPage( + name: _Paths.currencyListScreen, + page: () => responsiveWidget(CurrencyListScreen()), + ), + GetPage( + name: _Paths.FAQS_FIRST_SCREEN, + page: () => responsiveWidget(FaqsFirstScreenView()), + binding: FaqsFirstBinding(), + ), + GetPage( + name: _Paths.FAQS_SECOND_SCREEN, + page: () => responsiveWidget(FaqsSecondScreenView()), + binding: FaqsSecondBinding(), + ), + GetPage( + name: _Paths.FAQS_THIRD_SCREEN, + page: () => responsiveWidget(FaqsThirdScreenView()), + binding: FaqsThirdBinding(), + ), + GetPage( + name: _Paths.ADD_NEW_ACCOUNT, + page: () => responsiveWidget(const AddNewAccountView()), + binding: AddNewAccountBinding(), + ), + GetPage( + name: _Paths.CHANGE_TRANSACTION_PIN_OTP, + page: () => responsiveWidget(const ChangeTransactionPinOtpView()), + binding: ChangeTransactionPinOtpBinding(), + ), + GetPage( + name: _Paths.INTERNAL_TRANSACTION_OPT, + page: () => responsiveWidget(const InternalTransactionOtpView()), + binding: InternalTransactionOtpBinding(), + ), + ]; +} + +Widget responsiveWidget(Widget page, {double? value, Color? color}) { + // return page; + // dp("Width init", {MediaQuery.sizeOf(Get.context!).width}); + // dp("Height init ", MediaQuery.sizeOf(Get.context!).height); + + return r.MaxWidthBox( + maxWidth: 1300, + background: ColoredBox( + color: color ?? Colors.white, + ), + alignment: Alignment.bottomCenter, + child: r.ResponsiveScaledBox( + width: r.ResponsiveValue(Get.context!, conditionalValues: [ + //tested on device widht 184,203,165,170 + // height 361 + r.Condition.between(start: 0, end: 229, value: value ?? 470), + + r.Condition.between(start: 230, end: 320, value: value ?? 440), + //tested on device widht 360, 450=410 + r.Condition.between(start: 321, end: 480, value: value ?? 410), + // tested on device width = 540, 617 + r.Condition.between(start: 481, end: 640, value: value ?? 450), + // 952, 915 + r.Condition.between(start: 641, end: 960, value: value ?? 600), + // + r.Condition.between(start: 961, end: 1024, value: value ?? 650), + // 1030 , 1098, 1277 + r.Condition.between(start: 1025, end: 1280, value: value ?? 700), + // 1287 , + r.Condition.between(start: 1281, end: 1300, value: value ?? 750), + ]).value, + child: page, + ), + ); +} diff --git a/lib/app/routes/app_routes.dart b/lib/app/routes/app_routes.dart new file mode 100644 index 0000000..87f8d09 --- /dev/null +++ b/lib/app/routes/app_routes.dart @@ -0,0 +1,147 @@ +part of 'app_pages.dart'; +// DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart + +abstract class Routes { + Routes._(); + + static const SPLASH_SCREEN = _Paths.SPLASH_SCREEN; + static const INTRO_SCREEN = _Paths.INTRO_SCREEN; + static const LOGIN_SCREEN = _Paths.LOGIN_SCREEN; + static const DASHBOARD_SCREEN = _Paths.DASHBOARD_SCREEN; + static const SIGN_UP_SCREEN_STEP1 = _Paths.SIGN_UP_SCREEN_STEP1; + static const SIGN_UP_SCREEN_STEP2 = _Paths.SIGN_UP_SCREEN_STEP2; + static const SIGN_UP_SCREEN_STEP3 = _Paths.SIGN_UP_SCREEN_STEP3; + static const SIGN_UP_SCREEN_OTP = _Paths.SIGN_UP_SCREEN_OTP; + static const O_T_P_SCREEN = _Paths.O_T_P_SCREEN; + static const MY_ACCOUNT = _Paths.MY_ACCOUNT; + static const BILL_MANAGEMENT = _Paths.BILL_MANAGEMENT; + static const CHEQUE_MANAGEMENT = _Paths.CHEQUE_MANAGEMENT; + static const U_SEND = _Paths.U_SEND; + static const INTERNAL_ACCOUNT_TRANS = _Paths.INTERNAL_ACCOUNT_TRANS; + static const U_RECEIVED = _Paths.U_RECEIVED; + static const BENEFICIARY_MANAGEMENT = _Paths.BENEFICIARY_MANAGEMENT; + static const NEW_BENEFICIARY = _Paths.NEW_BENEFICIARY; + static const NEW_BENEFICIARY_OPT = _Paths.NEW_BENEFICIARY_OPT; + static const BENEFICIARY_TRANSFER_MONEY = _Paths.BENEFICIARY_TRANSFER_MONEY; + static const BENEFICIARY_TRANSFER_MONEY_OTP = _Paths.BENEFICIARY_TRANSFER_MONEY_OTP; + static const AGENT_LOCATION = _Paths.AGENT_LOCATION; + static const ACCOUNT_STATEMENT = _Paths.ACCOUNT_STATEMENT; + static const USER_PROFILE = _Paths.USER_PROFILE; + static const PRIVACY_POLICY = _Paths.PRIVACY_POLICY; + static const USER_ACTIVITY = _Paths.USER_ACTIVITY; + static const TRANSACTION_HISTORY = _Paths.TRANSACTION_HISTORY; + static const ABOUT_US = _Paths.ABOUT_US; + static const CAREER = _Paths.CAREER; + static const CONTACTS_SCREEN = _Paths.CONTACTS_SCREEN; + static const RECIPIENT_DETAILS = _Paths.RECIPIENT_DETAILS; + static const U_SEND_OTP = _Paths.U_SEND_OTP; + static const SAMPLE_FIELDS = _Paths.SAMPLE_FIELDS; + static const changePassword = _Paths.changePassword; + + static const faqsViews = _Paths.faqsView; + static const BILL_MANAGEMENT_CATEGORY = _Paths.BILL_MANAGEMENT_CATEGORY; + static const UTILITY_BILLS_PAYMENT = _Paths.UTILITY_BILLS_PAYMENT; + static const UTILITY_BILLS_SELECTED_CATEGORY = _Paths.UTILITY_BILLS_SELECTED_CATEGORY; + static const UTILITY_BILLS_SELECTED_CATEGORY_DETAILS = _Paths.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS; + static const CHEQUE_ACTIVATION = _Paths.CHEQUE_ACTIVATION; + static const CHEQUE_BOOK_REQUEST_DETAILS = _Paths.CHEQUE_BOOK_REQUEST_DETAILS; + static const CHEQUE_DEPOSIT = _Paths.CHEQUE_DEPOSIT; + static const CHEQUE_REQUEST = _Paths.CHEQUE_REQUEST; + static const CHEQUE_STATUS = _Paths.CHEQUE_STATUS; + static const CHEQUE_STATUS_HISTORY = _Paths.CHEQUE_STATUS_HISTORY; + static const APP_SETTING = _Paths.APP_SETTING; + static const DAIL_TRANSACTION_LIMIT = _Paths.DAIL_TRANSACTION_LIMIT; + static const CHANGE_TRANSACTION_PIN = _Paths.CHANGE_TRANSACTION_PIN; + static const CHANGE_TRANSACTION_PIN_OTP = _Paths.CHANGE_TRANSACTION_PIN_OTP; + static const QR_SETTING = _Paths.QR_SETTING; + static const NOTIFICATIONS = _Paths.NOTIFICATIONS; + static const CREATE_TRANSACTION_PIN = _Paths.CREATE_TRANSACTION_PIN; + static const TRANSACTION_PIN_OTP = _Paths.TRANSACTION_PIN_OTP; + static const CREATE_TRANSACTION_PIN_OTP = _Paths.CREATE_TRANSACTION_PIN_OTP; + static const qrViewScreen = _Paths.qrViewScreen; + static const qrScanView = _Paths.qrScanView; + static const PAYMENT_METHOD = _Paths.PAYMENT_METHOD; + static const GENERAL_LEDGER = _Paths.GENERAL_LEDGER; + static const OTP_ADD_MONEY = _Paths.OTP_ADD_MONEY; + static const currencyListScreen = _Paths.currencyListScreen; + static const ADD_MONEY = _Paths.ADD_MONEY; + static const ADD_MONEY_OTP = _Paths.ADD_MONEY_OTP; + static const FAQS_FIRST_SCREEN = _Paths.FAQS_FIRST_SCREEN; + static const FAQS_SECOND_SCREEN = _Paths.FAQS_SECOND_SCREEN; + static const FAQS_THIRD_SCREEN = _Paths.FAQS_THIRD_SCREEN; + static const ADD_NEW_ACCOUNT = _Paths.ADD_NEW_ACCOUNT; + static const INTERNAL_TRANSACTION_OPT = _Paths.INTERNAL_TRANSACTION_OPT; +} + +abstract class _Paths { + _Paths._(); + + static const SPLASH_SCREEN = '/splash-screen'; + static const INTRO_SCREEN = '/intro-screen'; + static const LOGIN_SCREEN = '/login-screen'; + static const DASHBOARD_SCREEN = '/dashboard-screen'; + static const SIGN_UP_SCREEN_STEP1 = '/sign-up-screen-step1'; + static const SIGN_UP_SCREEN_STEP2 = '/sign-up-screen-step2'; + static const SIGN_UP_SCREEN_STEP3 = '/sign-up-screen-step3'; + static const SIGN_UP_SCREEN_OTP = '/sign-up-screen-otp'; + static const O_T_P_SCREEN = '/o-t-p-screen'; + static const MY_ACCOUNT = '/my-account'; + static const BILL_MANAGEMENT = '/bill-management'; + static const CHEQUE_MANAGEMENT = '/cheque-management'; + static const U_SEND = '/u-send'; + static const INTERNAL_ACCOUNT_TRANS = '/internal-account-trans'; + static const U_RECEIVED = '/u-received'; + static const BENEFICIARY_MANAGEMENT = '/beneficiary-management'; + static const NEW_BENEFICIARY = '/new-beneficiary'; + static const NEW_BENEFICIARY_OPT = '/new-beneficiary-otp'; + static const BENEFICIARY_TRANSFER_MONEY = '/beneficiary-transfer-money'; + static const BENEFICIARY_TRANSFER_MONEY_OTP = '/beneficiary-transfer-money-otp'; + static const AGENT_LOCATION = '/agent-location'; + static const ACCOUNT_STATEMENT = '/account-statement'; + static const USER_PROFILE = '/user-profile'; + static const PRIVACY_POLICY = '/privacy-policy'; + static const USER_ACTIVITY = '/user-activity'; + static const TRANSACTION_HISTORY = '/transaction-history'; + static const ABOUT_US = '/about-us'; + static const CAREER = '/career'; + static const CONTACTS_SCREEN = '/contacts-screen'; + static const RECIPIENT_DETAILS = '/recipient-details'; + static const U_SEND_OTP = '/u-send-otp'; + static const SAMPLE_FIELDS = '/sample-fields'; + static const changePassword = '/change-password'; + static const qrViewScreen = '/qrViewScreen'; + static const qrScanView = '/qrScanView'; + + static const faqsView = '/faqs-view'; + static const BILL_MANAGEMENT_CATEGORY = '/bill-management-category'; + static const UTILITY_BILLS_PAYMENT = '/utility-bills-payment'; + static const UTILITY_BILLS_SELECTED_CATEGORY = '/utility-bills-selected-category'; + static const UTILITY_BILLS_SELECTED_CATEGORY_DETAILS = '/utility-bills-selected-category-details'; + + static const CHEQUE_ACTIVATION = '/cheque-activation'; + static const CHEQUE_BOOK_REQUEST_DETAILS = '/cheque-book-request-details'; + static const CHEQUE_DEPOSIT = '/cheque-deposit'; + static const CHEQUE_REQUEST = '/cheque-request'; + static const CHEQUE_STATUS = '/cheque-status'; + static const CHEQUE_STATUS_HISTORY = '/cheque-status-history'; + static const APP_SETTING = '/app-setting'; + static const DAIL_TRANSACTION_LIMIT = '/dail-transaction-limit'; + static const CHANGE_TRANSACTION_PIN = '/change-transaction-pin'; + static const CHANGE_TRANSACTION_PIN_OTP = '/change-transaction-pin-otp'; + static const INTERNAL_TRANSACTION_OPT = '/internal-transaction-otp'; + static const QR_SETTING = '/qr-setting'; + static const NOTIFICATIONS = '/notifications'; + static const CREATE_TRANSACTION_PIN = '/create-transaction-pin'; + static const TRANSACTION_PIN_OTP = '/transaction-pin-otp'; + static const CREATE_TRANSACTION_PIN_OTP = '/create-transaction-pin-otp'; + static const PAYMENT_METHOD = '/payment-method'; + static const GENERAL_LEDGER = '/general-ledger'; + static const OTP_ADD_MONEY = '/otp-add-money'; + static const ADD_MONEY = '/add-money'; + static const ADD_MONEY_OTP = '/add-money_otp'; + static const currencyListScreen = '/CurrencyListScreen'; + static const FAQS_FIRST_SCREEN = '/faqs-first-screen'; + static const FAQS_SECOND_SCREEN = '/faqs-second-screen'; + static const FAQS_THIRD_SCREEN = '/faqs-third-screen'; + static const ADD_NEW_ACCOUNT = '/add-new-account'; +} diff --git a/lib/main.dart b/lib/main.dart index 7b7f5b6..c695bfb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,122 +1,123 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +// import 'package:flutter_dotenv/flutter_dotenv.dart'; +// import 'package:flutter_windowmanager/flutter_windowmanager.dart'; +import 'package:get/get.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:loader_overlay/loader_overlay.dart'; +import 'package:responsive_framework/responsive_framework.dart'; +import 'app/bindings/dependency_injections.dart'; +import 'app/core/config/connectivity_service.dart'; +import 'app/core/utils/root_detector_device.dart'; +import 'app/core/utils/simulator_check.dart'; +import 'app/custom_widgets/custom_toasty.dart'; +import 'app/res/app_colors.dart'; +import 'app/res/app_theme.dart'; +import 'app/res/suppoted_languages.dart'; +import 'app/routes/app_pages.dart'; -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({super.key}); +void main() async { + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: AppColors.colorPrimary, + ), + ); + WidgetsFlutterBinding.ensureInitialized(); + // await dotenv.load(); + bool isRootedOrJailbroken = await isDeviceRootedOrJailbroken(); + bool isDeviceEmulator = await isEmulator(); + if (isRootedOrJailbroken || isDeviceEmulator) { + /// Display an error message and exit the app + String errorMessage = isDeviceEmulator ? "This app cannot run on emulators or simulators." : "Rooted or jailbroken device detected."; + Toasty.error(errorMessage); + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + return; + // runApp(const RootedOrJailbrokenDeviceApp()); + } else { + /// Retrieve and decrypt the URL + // final encryption = UrlEncryption(); + // String encryptedUrl = UrlEncryption().encryptData('https://uco.mfsys.ca'); + // print('Encrypted URL: $encryptedUrl'); + // + // String decryptedUrl = UrlEncryption().decryptData(encryptedUrl); + // print('Decrypted URL: $decryptedUrl'); - // 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 THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), - ); + // FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); + await Hive.initFlutter(); + runApp(const MyApp(apiKey: '',)); } } -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // 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; +class MyApp extends StatefulWidget { + final String apiKey; + const MyApp({Key? key, required this.apiKey}) : super(key: key); @override - State createState() => _MyHomePageState(); + State createState() => _MyAppState(); } -class _MyHomePageState extends State { - int _counter = 0; +class _MyAppState extends State { + ThemeData themeData = ThemeData(); + ConnectivityHelper connectivityHelper = ConnectivityHelper(); - void _incrementCounter() { + void changeTheme(ThemeMode themeMode) { 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++; + themeMode = themeMode; }); } + @override + void initState() { + // TODO: implement initState + super.initState(); + connectivityHelper.checkNetworkConnectivity(); + } + @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( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // 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. - // - // 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). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('You have pushed the button this many times:'), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(statusBarColor: AppColors.colorPrimary)); + + return GlobalLoaderOverlay( + useDefaultLoading: false, + overlayColor: Colors.black.withOpacity(0.2), + overlayWidgetBuilder: (progress) => const CircularProgressIndicator(), + child: GestureDetector( + onTap: () { + SystemChannels.textInput.invokeMethod('TextInput.hide'); + }, + child: GetMaterialApp( + theme: appTheme(), + defaultTransition: Transition.rightToLeftWithFade, + darkTheme: appTheme(), + debugShowCheckedModeBanner: false, + initialRoute: AppPages.INITIAL, + getPages: AppPages.routes, + initialBinding: DependencysInjections(), + locale: const Locale("en"), + translations: SupportedLanguages(), + fallbackLocale: const Locale('en', 'ar'), + builder: (context, child) { + return ResponsiveBreakpoints.builder( + child: BouncingScrollWrapper.builder(context, child!), + breakpoints: [ + const Breakpoint(start: 0, end: 229, name: "m1"), + const Breakpoint(start: 230, end: 320, name: "m2"), + const Breakpoint(start: 321, end: 480, name: "m3"), + const Breakpoint(start: 481, end: 640, name: "m4"), + const Breakpoint(start: 641, end: 960, name: "m5"), + const Breakpoint(start: 961, end: 1024, name: "m6"), + const Breakpoint(start: 1025, end: 1280, name: "m7"), + const Breakpoint(start: 1281, end: 1300, name: "m8"), + ], + ); + }, ), ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. ); } } diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..e79846c --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1514 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + url: "https://pub.dev" + source: hosted + version: "67.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + url: "https://pub.dev" + source: hosted + version: "6.4.1" + animated_toggle_switch: + dependency: "direct main" + description: + name: animated_toggle_switch + sha256: faecb2339cde5e7d299389cf7e01cf35305a3ba212ae8ff51c02ce8385d1d273 + url: "https://pub.dev" + source: hosted + version: "0.8.7" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: "9a8f69025044eb466b9b60ef3bc3ac99b4dc6c158ae9c56d25eeccf5bc56d024" + url: "https://pub.dev" + source: hosted + version: "1.6.5" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + back_button_interceptor: + dependency: transitive + description: + name: back_button_interceptor + sha256: "8354b03320043db546e3f446af171faaa71384100486444113628f7db1e7fe9b" + url: "https://pub.dev" + source: hosted + version: "7.0.3" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + buttons_tabbar: + dependency: "direct main" + description: + name: buttons_tabbar + sha256: "3f0969c26574ef15c0c9ff1dee42c3c4b0d3563d2c8607804372490fb8b76896" + url: "https://pub.dev" + source: hosted + version: "1.3.8" + calendar_date_picker2: + dependency: "direct main" + description: + name: calendar_date_picker2 + sha256: "7ff3f372faff6814a2ba69427d116fb9a3d52e28644b9de4b06db6638fdac798" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + camera: + dependency: "direct main" + description: + name: camera + sha256: dfa8fc5a1adaeb95e7a54d86a5bd56f4bb0e035515354c8ac6d262e35cec2ec8 + url: "https://pub.dev" + source: hosted + version: "0.10.6" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: "50c0d1c4b122163e3d7cdfcd6d4cd8078aac27d0f1cd1e7b3fa69e6b3f06f4b7" + url: "https://pub.dev" + source: hosted + version: "0.10.10+14" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "11b4aee2f5e5e038982e152b4a342c749b414aa27857899d20f4323e94cb5f0b" + url: "https://pub.dev" + source: hosted + version: "0.9.23+2" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: "98cfc9357e04bad617671b4c1f78a597f25f08003089dd94050709ae54effc63" + url: "https://pub.dev" + source: hosted + version: "2.12.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: "57f49a635c8bf249d07fb95eb693d7e4dda6796dedb3777f9127fb54847beba7" + url: "https://pub.dev" + source: hosted + version: "0.3.5+3" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + chunked_stream: + dependency: transitive + description: + name: chunked_stream + sha256: b2fde5f81d780f0c1699b8347cae2e413412ae947fc6e64727cc48c6bb54c95c + url: "https://pub.dev" + source: hosted + version: "1.4.2" + circular_buffer: + dependency: transitive + description: + name: circular_buffer + sha256: b3a315fef3fee7fe58879643fc8ce21c7c2449d01c1a8a396dc9e24687f335c4 + url: "https://pub.dev" + source: hosted + version: "0.12.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec + url: "https://pub.dev" + source: hosted + version: "6.1.5" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + country_code_picker: + dependency: "direct main" + description: + name: country_code_picker + sha256: "92818885f0e47486539f80463b66f649970506a91dd3c0731ca3ba5308324a4d" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" + url: "https://pub.dev" + source: hosted + version: "0.3.5+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + csv: + dependency: transitive + description: + name: csv + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c + url: "https://pub.dev" + source: hosted + version: "6.0.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_console: + dependency: transitive + description: + name: dart_console + sha256: "03c23e1f9cc3ac02b608f834808003e6510a5b292a0449f43dfac1c78bd8ee85" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 + url: "https://pub.dev" + source: hosted + version: "0.7.12" + dcli: + dependency: transitive + description: + name: dcli + sha256: "881e88bbad0ada4e3a085a0b55e05afa8e4199392c0c45ac18e3dedc37305b9b" + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_common: + dependency: transitive + description: + name: dcli_common + sha256: f8f77bea6a6d7e4ec2dc24cb4f274fc582938057c2cba44ed0650195ecfcd3ad + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_core: + dependency: transitive + description: + name: dcli_core + sha256: "29fb4833aa950900936646190b30315db511a853273b9fe31d360e5f72c7560b" + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_terminal: + dependency: transitive + description: + name: dcli_terminal + sha256: fb50860855c6b2841aed5bcfb315fa83d1401e109691b6585773a24c149dc4b0 + url: "https://pub.dev" + source: hosted + version: "6.1.2" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + url: "https://pub.dev" + source: hosted + version: "10.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" + dio: + dependency: "direct main" + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 + url: "https://pub.dev" + source: hosted + version: "2.3.9" + encrypt: + dependency: "direct main" + description: + name: encrypt + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_camera_overlay_new: + dependency: "direct main" + description: + name: flutter_camera_overlay_new + sha256: e7bdf4724c2355331c89dbb390c429fdf8307aef168ff1c9a8c9e0ed401e0f2f + url: "https://pub.dev" + source: hosted + version: "0.0.1" + flutter_contacts: + dependency: "direct main" + description: + name: flutter_contacts + sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" + flutter_custom_clippers: + dependency: "direct main" + description: + name: flutter_custom_clippers + sha256: "473e3daf61c2a6cee0ad137393259a25223239d519a131c7ec1cac04d06e5407" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b + url: "https://pub.dev" + source: hosted + version: "5.2.1" + flutter_form_builder: + dependency: "direct main" + description: + name: flutter_form_builder + sha256: "560eb5e367d81170c6ade1e7ae63ecc5167936ae2cdfaae8a345e91bce19d2f2" + url: "https://pub.dev" + source: hosted + version: "9.2.1" + flutter_keyboard_visibility: + dependency: "direct main" + description: + name: flutter_keyboard_visibility + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_platform_interface: + dependency: transitive + description: + name: flutter_keyboard_visibility_platform_interface + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_web: + dependency: transitive + description: + name: flutter_keyboard_visibility_web + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1 + url: "https://pub.dev" + source: hosted + version: "2.0.33" + flutter_rounded_date_picker: + dependency: "direct main" + description: + name: flutter_rounded_date_picker + sha256: e6aa2dc5d3b44e8bbe85ef901be69eac59ba4136427f11f4c8b2a303e1e774e7 + url: "https://pub.dev" + source: hosted + version: "3.0.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_timer_countdown: + dependency: "direct main" + description: + name: flutter_timer_countdown + sha256: "0c73e1593ad7949c007752199a17e7ed50bb581568743dbc32f061f49873219e" + url: "https://pub.dev" + source: hosted + version: "1.0.7" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_zoom_drawer: + dependency: "direct main" + description: + name: flutter_zoom_drawer + sha256: "8488e3c01de7adf066daa16643b7de5cdff26b2deb637cbfc10b1fcea7b66157" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "90778fe0497fe3a09166e8cf2e0867310ff434b794526589e77ec03cf08ba8e8" + url: "https://pub.dev" + source: hosted + version: "8.2.14" + functional_data: + dependency: transitive + description: + name: functional_data + sha256: "76d17dc707c40e552014f5a49c0afcc3f1e3f05e800cd6b7872940bfe41a5039" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + get: + dependency: "direct main" + description: + name: get + sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e + url: "https://pub.dev" + source: hosted + version: "4.6.6" + get_cli: + dependency: "direct main" + description: + name: get_cli + sha256: bac338bb889f8e72ec4d977ef3fe937e82339cb3e437d73582441fb4e43ef26f + url: "https://pub.dev" + source: hosted + version: "1.9.1" + getwidget: + dependency: "direct main" + description: + name: getwidget + sha256: "91df14a8d80e21f3ec02759295b90cc8badb8a872b90d34ad4aeb4085d833b5c" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: eefe5ee217f331627d8bbcf01f91b21c730bf66e225d6dc8a148370b0819168d + url: "https://pub.dev" + source: hosted + version: "7.0.0" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image: + dependency: "direct main" + description: + name: image + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + url: "https://pub.dev" + source: hosted + version: "4.3.0" + ini: + dependency: transitive + description: + name: ini + sha256: "12a76c53591ffdf86d1265be3f986888a6dfeb34a85957774bc65912d989a173" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + introduction_slider: + dependency: "direct main" + description: + name: introduction_slider + sha256: "0262f79d4eab0a0d9ffcedbb82e1120bac37ad8b7685a51de45a5386e847641d" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json2yaml: + dependency: transitive + description: + name: json2yaml + sha256: da94630fbc56079426fdd167ae58373286f603371075b69bf46d848d63ba3e51 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + lists: + dependency: transitive + description: + name: lists + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + loader_overlay: + dependency: "direct main" + description: + name: loader_overlay + sha256: "02deeeed0d4eaaeeada6ce7bb13426d7548acad1f71e4884ec4a010e0e4824d6" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467 + url: "https://pub.dev" + source: hosted + version: "1.0.56" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49" + url: "https://pub.dev" + source: hosted + version: "1.6.1" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 + url: "https://pub.dev" + source: hosted + version: "1.1.0" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 + url: "https://pub.dev" + source: hosted + version: "1.0.11" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + sha256: "0b466a0a8a211b366c2e87f3345715faef9b6011c7147556ad22f37de6ba3173" + url: "https://pub.dev" + source: hosted + version: "6.0.11" + native_synchronization_temp: + dependency: transitive + description: + name: native_synchronization_temp + sha256: f9ad36a5054c606db10e3dc0c9c352e6d0d56d08621af5c470abf9fa41da40fa + url: "https://pub.dev" + source: hosted + version: "0.7.1" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e + url: "https://pub.dev" + source: hosted + version: "2.2.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44" + url: "https://pub.dev" + source: hosted + version: "11.3.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + url: "https://pub.dev" + source: hosted + version: "12.1.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + url: "https://pub.dev" + source: hosted + version: "9.4.7" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" + url: "https://pub.dev" + source: hosted + version: "0.1.3+5" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 + url: "https://pub.dev" + source: hosted + version: "4.3.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + pin_code_fields: + dependency: "direct main" + description: + name: pin_code_fields + sha256: "4c0db7fbc889e622e7c71ea54b9ee624bb70c7365b532abea0271b17ea75b729" + url: "https://pub.dev" + source: hosted + version: "8.0.1" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointycastle: + dependency: "direct main" + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + process_run: + dependency: transitive + description: + name: process_run + sha256: "4e789d1ac24da46fdb61269fd85b42a08f787c752cc16b65f4cad5e4c20d37f8" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_lock: + dependency: transitive + description: + name: pubspec_lock + sha256: ed5fc1ecd0cdc0e14475a091afcb2c4cbb00e74cebff17635e9abbec18d76cc4 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + pubspec_manager: + dependency: transitive + description: + name: pubspec_manager + sha256: "416609635f6c53ab759223ae66e71282e61a863c13ec47d60381e4b8046c2a71" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + quickalert: + dependency: "direct main" + description: + name: quickalert + sha256: "0c21c9be68b9ae76082e1ad56db9f51202a38e617e08376f05375238277cfb5a" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + responsive_framework: + dependency: "direct main" + description: + name: responsive_framework + sha256: "52367ab0c3479b3a5342dec3b74a3d47c4cc1b45bb5d38f720c2e002ebccd4ee" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + root_checker_plus: + dependency: "direct main" + description: + name: root_checker_plus + sha256: "79087f93413240ac4842859eef55f8a63b748b402c4353b3446a558b1a352d16" + url: "https://pub.dev" + source: hosted + version: "0.0.7" + scope: + dependency: transitive + description: + name: scope + sha256: "0b056e5b64ca16a2db9e1eb35cf7fd05a9e99a6b15140f82bfa651d081e4819b" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + settings_yaml: + dependency: transitive + description: + name: settings_yaml + sha256: "8fec1ab4c6ed5efb61cd336e8a86d62c24026d97b08646db00e959d9cc7b11a2" + url: "https://pub.dev" + source: hosted + version: "8.3.1" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" + url: "https://pub.dev" + source: hosted + version: "12.0.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + simple_speed_dial: + dependency: "direct main" + description: + name: simple_speed_dial + sha256: b8322649ac3a6ab1ed1153e005efe90d48e6cb5b2b4e264ca0997cf1e88006fa + url: "https://pub.dev" + source: hosted + version: "0.1.7" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + url: "https://pub.dev" + source: hosted + version: "1.3.5" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + string_validator: + dependency: "direct main" + description: + name: string_validator + sha256: "54d4f42cd6878ae72793a58a529d9a18ebfdfbfebd9793bbe55c9b28935e8543" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + strings: + dependency: transitive + description: + name: strings + sha256: "052836499f03897d3860a603b330c1ea3c8a14177b21f34b15a1295f36024aae" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + stylish_bottom_bar: + dependency: "direct main" + description: + name: stylish_bottom_bar + sha256: "54970e4753b4273239b6dea0d1175c56beabcf39b5c65df4cbf86f1b86568d2b" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + sum_types: + dependency: transitive + description: + name: sum_types + sha256: c0a0fad9a518d011987e1d9f27fc336194294e55dafdc3699363e52aa5776e09 + url: "https://pub.dev" + source: hosted + version: "0.3.5" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + url: "https://pub.dev" + source: hosted + version: "3.4.0" + system_info2: + dependency: transitive + description: + name: system_info2 + sha256: b937736ecfa63c45b10dde1ceb6bb30e5c0c340e14c441df024150679d65ac43 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + url: "https://pub.dev" + source: hosted + version: "0.7.7" + timer_count_down: + dependency: "direct main" + description: + name: timer_count_down + sha256: d025d408c2654e497ca0bd4bde014bd7509d4c6397af4ed23a0f9b692bbcf337 + url: "https://pub.dev" + source: hosted + version: "2.2.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + unicode: + dependency: transitive + description: + name: unicode + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.dev" + source: hosted + version: "2.4.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + uuid: + dependency: transitive + description: + name: uuid + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 + url: "https://pub.dev" + source: hosted + version: "4.5.2" + validators2: + dependency: transitive + description: + name: validators2 + sha256: "4e9d7b13989d2a32b8e5ff21cec3e45b62a6eb826bc1d3deeb18963913c76e3a" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "201e876b5d52753626af64b6359cd13ac6011b80728731428fd34bc840f71c9b" + url: "https://pub.dev" + source: hosted + version: "1.1.20" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + version: + dependency: transitive + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.10.7 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index f13668d..2301600 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.9.2 + sdk: ^3.10.7 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -34,6 +34,62 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + get: 4.6.6 + google_fonts: 7.0.0 + hive_flutter: 1.1.0 + introduction_slider: 2.0.1 + flutter_custom_clippers: 2.1.0 + fluttertoast: ^8.2.12 + pin_code_fields: 8.0.1 + # url_launcher: ^6.3.2 + timer_count_down: 2.2.2 + flutter_timer_countdown: ^1.0.7 + flutter_zoom_drawer: 3.1.2 + quickalert: 1.0.2 + simple_speed_dial: 0.1.7 + stylish_bottom_bar: 1.0.3 + dropdown_button2: 2.3.9 + flutter_contacts: ^1.1.9+2 + permission_handler: 11.3.0 + flutter_form_builder: 9.2.1 + camera: ^0.10.5+2 + flutter_camera_overlay_new: 0.0.1 + flutter_svg: ^2.2.3 + responsive_framework: 1.4.0 + local_auth: 2.2.0 + dio: 4.0.6 + share_plus: ^12.0.1 + string_validator: 1.0.2 + country_code_picker: 3.0.0 + loader_overlay: 4.0.0 + getwidget: 4.0.0 + flutter_rounded_date_picker: 3.0.4 + calendar_date_picker2: 1.0.2 + json_serializable: 6.7.1 + buttons_tabbar: 1.3.8 + # google_maps_flutter: 2.14.0 + path_provider: 2.1.3 + # image_picker: ^1.2.1 + qr_flutter: ^4.1.0 + mobile_scanner: ^6.0.10 + screenshot: 3.0.0 + # image_gallery_saver: 2.0.1 + flutter_keyboard_visibility: 6.0.0 + # qr_code_scanner: + # git: + # url: https://github.com/liang-notes/qr_code_scanner + # ref: enable-scan-qrcode-from-gallery + animated_toggle_switch: ^0.8.2 + auto_size_text: ^3.0.0 + image: ^4.2.0 + connectivity_plus: ^6.0.3 + get_cli: ^1.8.0 + # flutter_windowmanager: ^0.2.0 + device_info_plus: ^10.1.0 + root_checker_plus: ^0.0.3 + encrypt: ^5.0.3 + pointycastle: ^3.9.1 + flutter_dotenv: ^5.1.0 dev_dependencies: flutter_test: @@ -44,7 +100,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^5.0.0 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -58,9 +114,13 @@ flutter: 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 + assets: + - assets/ + - assets/uco/ + - assets/uco/icons/ + - assets/uco/images/ + - assets/uco/logo/ + - assets/.en # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images @@ -73,11 +133,22 @@ flutter: # "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 + fonts: + - family: Inter + fonts: + - asset: fonts/Inter-Black.ttf + - asset: fonts/Inter-Bold.ttf + - asset: fonts/Inter-ExtraBold.ttf + - asset: fonts/Inter-ExtraLight.ttf + - asset: fonts/Inter-Light.ttf + - asset: fonts/Inter-Medium.ttf + - asset: fonts/Inter-Regular.ttf + - asset: fonts/Inter-SemiBold.ttf + - asset: fonts/Inter-Thin.ttf + - family: Poppins + fonts: + - asset: fonts/Poppins-Regular.ttf + - asset: fonts/Poppins-Medium.ttf # style: italic # - family: Trajan Pro # fonts: diff --git a/test/widget_test.dart b/test/widget_test.dart index ebd2222..f56e261 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,13 +7,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - import 'package:uco_mobile_poc/main.dart'; + void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const MyApp(apiKey: '',)); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);