From e602782eddefeb1ab5609bfc70569c661b86e315 Mon Sep 17 00:00:00 2001 From: Abdusalom G'ayratov Date: Thu, 4 Dec 2025 10:23:59 +0500 Subject: [PATCH] BASE: Update Icons & Name Of The App. --- android/app/src/main/res/ic_launcher-web.png | Bin 0 -> 32877 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 4 + .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9107 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 18883 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15732 bytes android/app/src/main/res/play_store_512.png | Bin 209796 -> 0 bytes android/app/src/main/res/playstore-icon.png | Bin 0 -> 34909 bytes .../res/values/ic_launcher_background.xml | 3 + android/app/src/main/res/values/styles.xml | 11 - .../translations/{en_En.json => en-US.json} | 4 +- assets/translations/ru-RU.json | 108 + assets/translations/ru_RU.json | 0 assets/translations/uz-UZ.json | 108 + assets/translations/uz_UZ.json | 0 lib/constant/constant.dart | 353 ++- .../0n_demand_payment_controller.dart | 400 ++- .../Intercity_home_controller.dart | 895 +++++-- lib/controllers/address_list_controller.dart | 7 +- .../advertisement_list_controller.dart | 2 +- .../all_brand_product_controller.dart | 22 +- .../all_category_product_controller.dart | 6 +- lib/controllers/book_parcel_controller.dart | 176 +- lib/controllers/cab_booking_controller.dart | 895 +++++-- .../cab_coupon_code_controller.dart | 6 +- lib/controllers/cab_dashboard_controller.dart | 19 +- lib/controllers/cab_home_controller.dart | 2 +- .../cab_order_details_controller.dart | 61 +- .../cab_rental_dashboard_controllers.dart | 20 +- lib/controllers/cab_review_controller.dart | 26 +- lib/controllers/cart_controller.dart | 594 ++++- lib/controllers/cashback_controller.dart | 2 +- .../category_restaurant_controller.dart | 14 +- .../change_language_controller.dart | 39 +- lib/controllers/chat_controller.dart | 47 +- lib/controllers/complain_controller.dart | 22 +- lib/controllers/dash_board_controller.dart | 36 +- .../dash_board_ecommarce_controller.dart | 21 +- .../dine_in_booking_controller.dart | 18 +- .../dine_in_booking_details_controller.dart | 2 +- lib/controllers/dine_in_controller.dart | 57 +- ...dine_in_restaurant_details_controller.dart | 231 +- .../discount_restaurant_list_controller.dart | 2 +- lib/controllers/edit_profile_controller.dart | 18 +- .../enter_manually_location_controller.dart | 22 +- lib/controllers/favourite_controller.dart | 67 +- .../favourite_ondemmand_controller.dart | 43 +- lib/controllers/food_home_controller.dart | 51 +- .../forgot_password_controller.dart | 9 +- lib/controllers/gift_card_controller.dart | 606 +++-- .../global_setting_controller.dart | 34 +- .../history_gift_card_controller.dart | 13 +- .../home_e_commerce_controller.dart | 30 +- lib/controllers/home_parcel_controller.dart | 2 +- lib/controllers/live_tracking_controller.dart | 188 +- lib/controllers/login_controller.dart | 144 +- lib/controllers/map_view_controller.dart | 2 +- lib/controllers/mobile_login_controller.dart | 26 +- .../my_booking_on_demand_controller.dart | 36 +- .../my_cab_booking_controller.dart | 304 ++- lib/controllers/my_profile_controller.dart | 7 +- .../my_rental_booking_controller.dart | 140 +- lib/controllers/on_boarding_controller.dart | 2 +- .../on_demand_booking_controller.dart | 80 +- .../on_demand_category_controller.dart | 3 +- .../on_demand_dashboard_controller.dart | 14 +- .../on_demand_details_controller.dart | 36 +- .../on_demand_home_controller.dart | 66 +- .../on_demand_order_details_controller.dart | 88 +- .../on_demand_review_controller.dart | 75 +- lib/controllers/order_controller.dart | 27 +- lib/controllers/order_details_controller.dart | 51 +- lib/controllers/order_placing_controller.dart | 2 +- .../osm_search_place_controller.dart | 5 +- .../otp_verification_controller.dart | 37 +- lib/controllers/parcel_coupon_controller.dart | 11 +- .../parcel_dashboard_controller.dart | 19 +- .../parcel_my_booking_controller.dart | 55 +- .../parcel_order_confirmation_controller.dart | 2 +- .../parcel_order_details_controller.dart | 52 +- lib/controllers/parcel_review_controller.dart | 23 +- lib/controllers/provider_controller.dart | 9 +- lib/controllers/rate_product_controller.dart | 87 +- .../redeem_gift_card_controller.dart | 2 +- lib/controllers/refer_friend_controller.dart | 2 +- .../rental_conformation_controller.dart | 32 +- lib/controllers/rental_coupon_controller.dart | 11 +- lib/controllers/rental_home_controller.dart | 122 +- .../rental_order_details_controller.dart | 412 ++- lib/controllers/rental_review_controller.dart | 26 +- .../restaurant_details_controller.dart | 150 +- .../restaurant_list_controller.dart | 2 +- lib/controllers/review_list_controller.dart | 2 +- lib/controllers/scan_qr_code_controller.dart | 2 +- lib/controllers/search_controller.dart | 15 +- lib/controllers/service_list_controller.dart | 2 +- lib/controllers/sign_up_controller.dart | 48 +- lib/controllers/splash_controller.dart | 21 +- lib/controllers/theme_controller.dart | 4 +- .../view_all_category_controller.dart | 15 +- .../view_all_popular_service_controller.dart | 42 +- .../view_category_service_controller.dart | 32 +- lib/controllers/wallet_controller.dart | 278 +- lib/main.dart | 2 + lib/payment/MercadoPagoScreen.dart | 23 +- lib/payment/PayFastScreen.dart | 19 +- lib/payment/midtrans_screen.dart | 28 +- lib/payment/orangePayScreen.dart | 63 +- lib/payment/paystack/pay_stack_screen.dart | 118 +- lib/payment/xenditScreen.dart | 35 +- .../auth_screens/forgot_password_screen.dart | 2 +- lib/screen_ui/auth_screens/login_screen.dart | 11 +- .../auth_screens/mobile_login_screen.dart | 2 +- .../auth_screens/otp_verification_screen.dart | 2 +- .../auth_screens/sign_up_screen.dart | 2 +- .../Intercity_home_screen.dart | 2299 +++++++++++++--- .../cab_booking_screen.dart | 58 +- .../cab_coupon_code_screen.dart | 132 +- .../cab_dashboard_screen.dart | 2 +- .../cab_service_screens/cab_home_screen.dart | 7 +- .../cab_order_details.dart | 2 +- .../cab_review_screen.dart | 2 +- .../cab_service_screens/complain_screen.dart | 48 +- .../my_cab_booking_screen.dart | 707 ++++- .../ecommarce/all_brand_product_screen.dart | 185 +- .../all_category_product_screen.dart | 183 +- .../dash_board_e_commerce_screen.dart | 100 +- .../ecommarce/home_e_commerce_screen.dart | 1252 +++++++-- .../address_list_screen.dart | 172 +- .../enter_manually_location.dart | 314 ++- .../location_permission_screen.dart | 101 +- .../maintenance_mode_screen.dart | 18 +- .../all_advertisement_screen.dart | 204 +- .../cart_screen/cart_screen.dart | 1964 +++++++++++--- .../cart_screen/coupon_list_screen.dart | 163 +- .../cart_screen/oder_placing_screens.dart | 226 +- .../cart_screen/select_payment_screen.dart | 3 +- .../cashback_screen/cashback_offers_list.dart | 73 +- .../change_language_screen.dart | 3 +- .../chat_screens/chat_screen.dart | 264 +- .../chat_screens/driver_inbox_screen.dart | 74 +- .../chat_screens/restaurant_inbox_screen.dart | 78 +- .../dash_board_screens/dash_board_screen.dart | 100 +- .../dine_in_booking_details.dart | 280 +- .../dine_in_booking_screen.dart | 222 +- .../dine_in_screeen/book_table_screen.dart | 432 ++- .../dine_in_details_screen.dart | 877 +++++-- .../dine_in_restaurant_list_screen.dart | 44 +- .../dine_in_screeen/dine_in_screen.dart | 2 +- .../view_all_category_dine_in_screen.dart | 98 +- .../edit_profile_screen.dart | 139 +- .../favourite_screens/favourite_screen.dart | 1022 ++++++-- .../forgot_password_screen.dart | 42 +- .../gift_card/gift_card_screen.dart | 280 +- .../gift_card/history_gift_card.dart | 223 +- .../gift_card/redeem_gift_card_screen.dart | 109 +- .../gift_card/select_gift_payment_screen.dart | 368 ++- .../category_restaurant_screen.dart | 213 +- .../discount_restaurant_list_screen.dart | 198 +- .../home_screen/home_screen.dart | 5 +- .../home_screen/home_screen_two.dart | 1139 ++++++-- .../home_screen/restaurant_list_screen.dart | 273 +- .../home_screen/story_view.dart | 73 +- .../home_screen/view_all_category_screen.dart | 82 +- .../live_tracking_screen.dart | 52 +- .../order_details_screen.dart | 1804 ++++++++++--- .../order_list_screen/order_screen.dart | 353 ++- .../profile_screen/profile_screen.dart | 591 ++++- .../rate_us_screen/rate_product_screen.dart | 357 ++- .../refer_friend_screen.dart | 154 +- .../restaurant_details_screen.dart | 2321 ++++++++++++++--- .../review_list_screen.dart | 231 +- .../scan_qr_code_screen.dart | 27 +- .../search_screen/search_screen.dart | 632 ++++- .../terms_and_condition_screen.dart | 31 +- .../wallet_screen/payment_list_screen.dart | 314 ++- .../wallet_screen/wallet_screen.dart | 251 +- .../on_boarding_screen.dart | 53 +- .../favourite_ondemand_screen.dart | 521 +++- .../my_booking_on_demand_screen.dart | 318 ++- .../on_demand_booking_screen.dart | 616 ++++- .../on_demand_category_screen.dart | 85 +- .../on_demand_dashboard_screen.dart | 100 +- .../on_demand_details_screen.dart | 602 ++++- .../on_demand_home_screen.dart | 453 +++- .../on_demand_order_details_screen.dart | 1726 ++++++++++-- .../on_demand_payment_screen.dart | 486 +++- .../on_demand_review_screen.dart | 126 +- .../provider_inbox_screen.dart | 74 +- .../on_demand_service/provider_screen.dart | 106 +- .../view_all_popular_service_screen.dart | 58 +- .../view_category_service_screen.dart | 40 +- .../worker_inbox_screen.dart | 78 +- .../parcel_service/book_parcel_screen.dart | 425 ++- .../parcel_service/home_parcel_screen.dart | 190 +- .../parcel_service/my_booking_screen.dart | 222 +- .../order_successfully_placed.dart | 29 +- .../parcel_service/parcel_coupon_screen.dart | 128 +- .../parcel_dashboard_screen.dart | 85 +- .../parcel_order_confirmation.dart | 918 +++++-- .../parcel_service/parcel_order_details.dart | 710 ++++- .../parcel_service/parcel_review_screen.dart | 174 +- .../my_rental_booking_screen.dart | 462 +++- .../rental_conformation_screen.dart | 470 +++- .../rental_service/rental_coupon_screen.dart | 128 +- .../rental_dashboard_screen.dart | 83 +- .../rental_service/rental_home_screen.dart | 680 ++++- .../rental_order_details_screen.dart | 1403 ++++++++-- .../rental_service/rental_review_screen.dart | 149 +- .../service_list_screen.dart | 12 +- .../splash_screen/splash_screen.dart | 9 +- lib/service/cart_provider.dart | 21 +- lib/service/fire_store_utils.dart | 4 +- lib/service/localization_service.dart | 2 +- lib/themes/custom_dialog_box.dart | 69 +- lib/themes/easy_loading_config.dart | 2 +- lib/themes/round_button_border.dart | 37 +- lib/themes/round_button_fill.dart | 39 +- lib/themes/text_field_widget.dart | 75 +- lib/utils/utils.dart | 2 +- .../src/widgets/defaults/empty_screen.dart | 6 +- lib/widget/osm_map/map_controller.dart | 35 +- lib/widget/osm_map/map_picker_page.dart | 2 +- lib/widget/permission_dialog.dart | 19 +- .../place_picker/location_controller.dart | 28 +- .../place_picker/location_picker_screen.dart | 2 +- .../story_view/widgets/story_image.dart | 2 - pubspec.yaml | 2 +- 228 files changed, 34364 insertions(+), 7905 deletions(-) create mode 100644 android/app/src/main/res/ic_launcher-web.png create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 android/app/src/main/res/play_store_512.png create mode 100644 android/app/src/main/res/playstore-icon.png create mode 100644 android/app/src/main/res/values/ic_launcher_background.xml delete mode 100644 android/app/src/main/res/values/styles.xml rename assets/translations/{en_En.json => en-US.json} (96%) create mode 100644 assets/translations/ru-RU.json delete mode 100644 assets/translations/ru_RU.json create mode 100644 assets/translations/uz-UZ.json delete mode 100644 assets/translations/uz_UZ.json diff --git a/android/app/src/main/res/ic_launcher-web.png b/android/app/src/main/res/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..97553a3be8c2fda69ed07635b07e345886ff975a GIT binary patch literal 32877 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 - + - \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..79d695e --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..62a0b5188c750204e3c0ce841e1662db3d5472a1 GIT binary patch literal 9107 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%0AC@f+KP{ur@NmiOzlc4yCz5WidHV`BB$6gu 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 K#cM^4g8mCb)J3O?TgX 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
pHpvv;x26m`&ynd7iaVZB z()X;N+PU|P9NDmOqsOyDBOm^*=qe)EYsP--^#ZwN);(~W(3ARDe0rC0ynroa;ig@y zCyjF03fC}2FY0!ef7wPBAI9iOt%!J68*}t(gr(Wi7eav6oP$}TY_Hb)n=chno=VG< z?9nZU(=hyLZYf)MP3nlmkwKt-1-S{z@lghM&tGMO&T#yb?W9}EJihAYEN@@~_#t+D z=)yQ9F*KNpXh50Rh?tSkSfv~a($gRp0fv&!;V=jL8xs8q^sZsG!ta5s!b7zMPUvDJj>u==s5?x&eFjG7>@=A$dO`QF z5oJ^a>b^OUcRBRs7@nVW8!@V^O(E8lYFW?ZqKEa-@o1)M$t*#e3QbY#i`RLzu|lVN zU*#ZhsBa~y+47y%iG2*OWok*lNsilbt|0B4ggCoSmDtCloxk=?fxM*{8nHf33itg9 zjjcUyg9exZn;24~Dx+P9D5KR)dDzda7x;lpGeeV6sJ(0ObBwBa;|FakApgg`CcubB zArX^)J<@&i-L(atJ<+@??AR8iH-p*+-?YQ0gTZJk8~b&R;%O^*_p??ko#Ggd2#AN_ z9ItyZxddcIZpn5_h9>#&k?B6=BY;jeF&`oJUG^IKyF2&cM)n;tIX`9p+BrpYDJ91L z*yuRM^d{7cFp$IPOH_pHLpH&gn=h{YIhI8hdo+W{bd1mE3-M>UjjZ(PfvG@M^1x&N zvDDA6AOq}?>WRe8RP|_m-oLWpSK3dF0Y}@6*jF2Cel4KK&&Nya6?p#-UvJqJXS8)` z7w+y>K(Hie1$VdLAqnmTE8JazI|L6Ng1fuBySqbhE2Ii&&inT1@${Ge2W!l6?{)97 z_L|p(yX$Uu#9iT!)~6J{;?j1`CP>x2vLKjQtouvP8O1#C5t)c;*dl4I)vu`jnTpFm zd6wfgoPKG{n-rjUjw!9&r9IyN%Ef~sDXs72KSuaOv@gru!~S_vc=ytZ;#Ja9a8i1v*g$L!)tAf_Smk!@ zcUppQHCYZaawsV;s60Mjp!jQW9&36_{4L%1wPDIu2iLNOwY;HQL`d>_74fziDnFFQ zvTeA-sZo=;H*HjCa>rH#Gt;CU9odf^f>unC@{fE^#xX98u=^(gWQhfLQ8jd<2 zqrd0+cwU>UNxv3fF&VlpTSw754XPd@DtGlzB5!0|D$s4+_leYJB;SJvv}3M{*f2X9 zuME4a)ny^8 z;4E=fbCfxuf^PA$_h}m_b*LXS(OAE+0g)V7IT^u{U)x#dPub5G=# zg&XLu4$J4h;aTYXcmImwSL-LUQ=U&fe%ijRJu0#SZihc#W>cmme;`oq=0m^lC7jsy z*!;~4=hOYkB>l%_@Rpy#88t1>@V;0HuDGLmT7lZ>IyhwI!j%b`x5J z?Sr9sfk^y98uBfs#)ZCS{!eRUY*+Ie@w8T6On6E0#!cvixVOBk5N`#u8dXEE022?1 zopqQMCG7wr#nSuAO#OdnfUU1bBEfQZ{I`^qVn+q%^-m6@K?2uIj5K1IqEIToy9?e| zKS-;yTzM`&I+GEBUPCXo4~?P^G+hq!>XcJ_xQxlQGbR1o8%m zqA>yzgbT1qL-`~rGdYnf3hL*0`1iNOT_&Gn#D!eoV;a%Qk+$|uWwCk0d1bdTtqHq) ziEqQ}Cb)9Un>_D(K9j4HHxZ94dtax%sdgD~4AJjpW9;#PV;a-7^tPWp(!$9)!(Vvvr?_2@)ADy!$3c9b}WXlnL`gzIj{aX7l`P-DWFC3_LQ>+9s!^<0@ z?{jo-C~mLMOu}X&MVx#lp56bn?iDs5T4|gt z^42zt-9tbMJG$R}Yo=@a`29rqW3nKIKiDzz_&%CrNEXqqVNQqp23WpF?WiY}KUC#U zgOgU)#;mQGz1;_rY@J{^tD&qCgiES z2jDFZcCER%`u9?)>5b22=wYKT?FVP-LR z?9(^-fnH>V^AB1E8Hs0!I%*^zCw7nE$F3X6ubr>8)VrH957V!(3DLi^N%vk_I*A(% znM^MaeNb;U*GBVO;mGk^(QEm!0S#v-6r)d#jSb{zJDfO;v<^{Z#6=6~#oaq=?kAS` zwV|MkH>r*e@>22DPzJ5See@`-u`24TTVb0ow%2;T%v&Tc@JX)gUmaeLruB(_4qwfm z^%DEohE&A!q!K;SG~vq8pDpoA!cq}OgHwpi$ILw(Z_$uwcAiL6TPG$|YUJnlDg98Z zlmvusa(_Ml@c;!dV6!L|085&M%L2D#f%rDV^8+E{sh4eiu?}HDO1aAt65X8QC=AL{y}g z^*Fj>23aVe{=P#tu#Vkv_WPQ#+kMoq|D$TKTru*v^CTrL7m?4R9#lMib$eCKhZ5A6e z9c1q{R1FHGT(GCZWf}l#Z{zETdlM3OV|9iOsN-MLb6&Jq@(p*xIm3b=^ty~^2Bu%Q zHfA)mpK`bi8oR$=5C*#~ztn!2hrcWS^iUt``$c)3hhF8^6D_KDUYF<+F@D-37Hr_n(fs1y{Jb)wVQij<9LkRN_ndu!}oG@|_*mPZ_Q1Kn-d2r)J zsAbA!L8$)7k3$m0`>kevDxm!#9MPs^CM|ERl}0|%KaNIA#aalvd(t>pi`mnX9m3hys!{l!fi zytLHZny%%Lof-1H4fK~V=cd(q|LACSNVY%*g`1WUKmWZDI*C|yPvl1Z-Ji>@F7D!5 z-QVw3bnGcDoA!}-*momF@RYOJWQJ!EQh)Zt>y`&GRgEXrrW1kR1RtYMJgIweY+7Zc zSVuRD{!SA2K_=j?C!fxEWaIw`lU2(bYnR9&C;04d^Msh-HZs2&0!#}}2@Ty|+mbRx ztQquIO>lwE(Zr{ntJrnmytTrOTl<6k9|E@%1S7SV4ZxnC=}D==n?sgQY zH|vMewZl{7JI&;1W~h@9eTxAfe6>?)f%BoOem)^EFVi^rgWdeecHh?DUJ>WsPwTwY z17n}JrJ>_mme^&*^;N$dYtGP2(yJ#A!vnaM1OB}^XtCX!n}SgS55O81LTW#bz$3*Z zpJ#I#BCx{~zHfbV+rnD1ey*nHYqs-1+90mMcRX0eWXg{92sGQGG?ZKDd@hRY-W0`t z^Y^p(PoRBpzzpe0I`$=epxDH@ciO08>)<{CZ1Arxm(m1(z2CB`6(fZlI@@Qst7^G~ z8E&6s{Q516sW`)_0K`fZ{A(C%9(*pcx$k!a6?~<+8eA^S%5U09p6xJZ&U)6C;eBk+ z4CQ5ahR5ju)y@@Pq!A#HdVAPe=6JOjm}pHmgm}v8F=^Eau*`LrY$CmnBJq=kp64m0 zwz^)H@$KeVdx*6>n;GJ^iD&Japyn$YHIj?i|&WkF`W&;3MJR~nI1gQ z5O|N3t{xztI;UjKT`O-~ODg1X+5Q6OgV@;rROUVd^)1BF=^sH@ccuZGih*+nPOWbNa7fCcQ&#c$U7c1NEKk!3opmPY!YmQP#f-)g}~;6~?Bc zUtJ6h zwv)lEqD@M7GsEtGX91uQprqc{M6wcEffrHSy?`Uzgm3zl8bDv7@B|_UF9c;`0wMEM z-lgcslP$sMVuKzGi2z5mr;Dbyr&F4=n19^OhxNOg+>4JqJ(Vw;$GeOdUFHxW)N&h& zqvK;ZNd|c5G|o0)d`re;7jEemiKyn3(dm*Q=z=kIVtb?53%PbuantL&5_=anJ93?m z0)Aab*St-N{_Wu{hfW49DBv6f#d=GkF3x^vy&~i=nV#Sh z(B#%l9wk0mOLdX1tZbJyjR|M;yHgReJF>NW*|AUZSXEhFG7BBr^Jz2Qxrw;xSIojm zwXp)llxZBTIZy5GbD^#|qh?Fp)NdhslC*MX;#6A$ z^EsIzVCUwI`8^#Rw7Y!8i4fUvpS-F=`9~qebArHo+^+R2o%YuktOz@(I>1jmP-yX* zi{{g6E&G$!e+=9@z>vXThX-(L!&-Xk&l5V{cK9o((~ZCvg!s@w3`1y6W$#26Y6^Whc?&70X{nzG8tVNfuj-t#cz@ocnDi3{UyD z%5~aV>H60dWOJvDmlkv~NDp`?6Wrz~%&SM+V0WJi@c;!yzVEm6pGrj|W@`o|S8RWJ zd5n(^8Yw=8`R=T@Pf4N@og85M@7PTS=Jxa3bEV20+c1BLHTugqiF|aPCuZ*y%ANRh zTJH`#jLvBnc}sstFr_5=@+}*~yzVhUp+#3T#gZah3}%|mhxu~+8okh%&>vb_Y1DiKbVI8MwTC>4Wh8+L{%c>2>!@`|Mn?5fq1kSI zOXY_eWJf)Bqp~HfzQo-x$KR`WlGpF6joO+nh;dMYvz|`Fb$({M z+I_3e-6HM2vi`Y=R_snXsDD&d=ETMck0-IjDQ<^mV(eXgPO55i*Q)B+YBFG*4sKn5 zlW?R=@APE9l~@0wHa z{r#OhUY$@`rS5@I82I;Kcc_i$JgYAu$qlwZG#LsvdE(n!rsd``u7-xhQdUE4wyriHEV}xdmELrHyTnWz5EL5q9+!u}eU)^J zra;PRHvvARdaaP}Mee$;FPoYZuV`|n>17Kui@iXE%_$_W)m9v6 zb2C-QT&Ml$YjRodU6bdTG{moVu|l%msNlrRkqMRZ5Hlz5{_78tvxY;nsBCIA{5lxe zaKknTHD)o#yyKx3Yn?E2bEzfo)3FiEM;ESf&{Lm_eHh>LgTBJ~A_n3BX7x{94G>mO zgpMj|Oe$&vW>z*WO^22i*Kcd~7Mn)5^&6#uC?>cGQ;I!&q)?!de;2CGel6VH@?)(} zNFtg7k9k9Q;l*>BC0rc!#k1e52H^(?d)7v6_OpjO*=)X@nRHzmIg&U&M&g3YMQ{`k$VEfN z3rwU5?g@D>j)otez~zqR+XxCba-JwzwlvSaHP zAbEdFJo-Op7A8+Sh(iv$?}qaA!~6bFCAhVfrq9Q5NXgRWFSLvf+$pMcDpad`{^{PZ z=%h_Lto^tWakuGVER-W}dK`^W18&xrvhkgSABd~YZat=f8y=iS-pui+<-VI_{B079 zc5>Q@#Nk8hf!L+Cvy@%6D!SaG5p+cObX+Eu?Sv4C^>awI3TkGfM@kW4lD;_@tz|!W zvJdnuq6~S?bzD0&3b}K|p>1*xR2=N%HTpjFH?*~f^!L9$*PT}WKS=SGN+#$QH&r05 zv;-vTz;GMg+~H#~9EuF`RK6dJLH8rvKjUhTyox@HH^p(q1@jZUo0G&zu9fI=&w^XF zCi=96j-KcvH^Wz)1d^cWnq|d?LTVo&$NKzh;U;txJ7YY3EqSy4C;nPw`!LSV-KX8)3s|9_ z-?{+7q|?y%RSoSHjH9e*la3Ryy?D*xcU2F3LsUwllUv|Das2ceQ0l?2@P2{!Nb_Hv znI_^my)*JXotUssDlsQ;>E1oyJN9wSl$nb8D{0c^L)DF!t?pwn`-x0VHLQy&Epv`LEiy3g33z-kt&ANkI zxVcKlji~o8HKD6FHQ^Xf3S4%|`!U`|+QbKAdKn59bmd-2Kay-Nehj+j$&ZG$(guuy?Fpt+( zOc41rO*y*%UTF{{{XAxq5ey(x(?;5i&IiDgd7z2)mD82z+1?PJr)JH~;2;#3FF5tP zyi|)GKke=tJRI(deEp2opk;)LjIkMAYQNd|QTpS%dJ#%6mOuHAmMA)087I_e8HJ}S z9vTLN&v|USGb#uY4%G20n+*Rr)+R~K{^ai2#L+V`zPF>jXYh_AI9*10`l|WvBDsE{ z0cDMHf9VYs`1x&HRp*jgbn$T&@ZBPLe{Jiw`reKn?_!u?)z;i$NkejPp7^Wn_5#sT zjfm(g!6bc@Q^kFeSgN1B$g2;l4>7g*84mo@;;KrWd-=26aph-p74JO;4HNur3lxk_ z7>9knkxTMV29|n}n0jQf=ucD&nYc1u|0(=sY0^(*-3Ro0Py((%5OY7nzX$f33dLw1A3wHzt~u|K2CsN16}1vjT9kQwkZ}#wEjc=pPjCpLil5Yia=K8 zv2evMH}mNH!lpkRD>AQ9>cLSWYvH?w0)}T4tRMeYvN}PvM<50DJpvA=!i`k_Qa1-h zq{;0n-#7@@pX>eMd9*xyZ~+n=ZXD^&Eeiyj$TTuO_o|maN-Dru`yS6LhIo*~@VR}H zQqLd4s&FtgRyEH*S2YgBZeB-O^eUP?abX_Ma4SwaA$PJO!=oyy;-|6CBN9dROR+L7 zzmZ2Wo;y?TGyv|Ro-awS`T3vSMg>lu9CCUp20UZ9Q8Mn~ z!sX@ZOp}K_z?QsJ-(5yt-&HE2lu+Sp2x=EBo6Vz5XdVgUym~N>leOpB{HDHjd4QXuY z@UXM+k|9gQ06fVWJ1F*!7^*~fJAOI*eSk_!heBm#-93E(uoa~_ z>-7N>v^HeSVA)TVL^Qy;1hhwe){Rb$jc5T`U2r`ABv&WXn3c=DU=>75{kSyQuyioL zSRg`wuuaytO3M+BzO+8t9z234Im8mPV`KYHXSGBmeHwL?h$u0kP763@Y;n1D~ zLUXeYjr4s?Is%IP%3!PBDI+QX84<5_ZEHN;34f(1THX+{v#d;de>idJ#%lGgZk_Ph z`uHD=WhUudTCjVDT>pj{&Jm!<;oM)DJ=@BumAgHz&~_AMHRJxZO@l)`lfweN7$N>A zYGcRoLMF4GcT6!m<8_|~!rtAwDe=F?`h^=Hz|yxw9bX3Q82wIFC_e=si4S%x>EGC} z>+T}YHNBZEpyOl*;1Y^jFjP{-O6rI1IOAjYwmz2P&u8mMs*$Ntzez0Qs+7 z=lbWYUt=B|fYfD`AkVTv-wxZRVZjek1k7W`Hd8}j+dpal5e$T)#|E*;lYEgv*m9f? zbAJpHQ8eBe;Enl#W)}3eP=c4-`;#YrhDWz}Q}w2jtlaLj)FDmN!BKoA z@6(cCHb8#WEE6$BBVMTnn^3WDJfu`;na9U z9_faBShY|f3K`^{`nC#nm`+?LzHwC5h@vMY@B822H7hjIbEx41%7AgFCK%uG36sAA zS8%vL%H$#bnk!3;$!ed~$bvzz({(&t(yyV|%XBB}WvJL+ntQA?+6celF^hr>&7P8p zv7%J7QiRg!Z|sRLzDXn7%4J-6B^bQY&*YGe z7Vb@G#eAGv(Z&1w0#myy?1NRh@Z1n3Ngz>jdYo{X5#3#s__FI_s_i(BeA!(OsVe?> z3a1`2hvrd+_(b)QPd_VTsgQ$@UVvU?DxB#9B4$uDN`fL=KZpNG?Spn8hkWp~54yys z#`a063K8Vh?ZE)E5Zz!xLcq)D0PUs#kuEwtei!K4C=STCj$y-2$6?0Gdc@}(A?}XH zN3FU*D2t;=SY7jpZyj5s+)ySukt*o=hp_S zemK9K4#5OH9b=B@ME~%3{>&Rt%-hpU@&^ zCrEWEcWUkm?HZh}hUa6m_(spn8`Cg=88Vx?w!$X&91g9XGJ^YU_{-uYa96U63V%}Q z*7F%5x!!keCwn`mur*X0M8;PSTKmp&%FPl%ElJB**sdVp`_7>T<@blbV&ZUO9?N`t zI)y(+XPN%1(0TdWWR0{onb?^UMCfs*#x=oa1(!EV!%*>5_oFq zDTnNe%{Tlz>sv*;nd9REj>%R8-moesuYXp6e*>ITDIKYW&g2rq-xfVgne*D_%Xr$G z9fZ+#wM;KB)sZwio8u(7O_{fx!LOfU2>i)V**ycC+thuqd01k%E-8zI)8U&1EMx7x zkh_kTLR2ahQj?XI!uV_TF8kJuL3YxDn0IUKp@;{8Mk>TC2lVG^vC^xua-rf_@cynG z%MC>kZRRo4{O76ySN+|CB-u=vf%&22o&{BVDH|PP+p^|rMpt&9tBmPG69Sjqg&u(q zk5J$68)ijcDPdc~Oy;L#(v&S56RYWIey1{DKI|7oh-ZTn94O#c1c?pqA`G=f3@vicsy z@A@7qO>QfX2N6-D+vLkLoFJ8MyiCdd=sR9lvBVDdiKCn8s1{YQQTLCttP69jdix4E zzr$btHa&=e#U-cxs!pp2$!!sbk)1tSSX{70CjhRK_Ad*FFHH!#F^Blm5`imeJKcVq zhZixUZDznI$s6Z7AeuxR!D@_?314$srt0g@`9N;MA)uiTpss$PsQwCNovnKQu73FM zSp|z((a-oMp>atwp8K5#$qckl`8dhyS?(?NT}E9vHD0};L9H552NR@479;c1-|vm` zX*lUYk$7dXt~k{PJqlj$ci<)Mnc26l?Mutuf+zg7;C}b~{NVbdCg2!Ip!Yqo^n5{2 z;p`W7SHLi`$EMDhxutw^he*K(&Ts)C^n(qO!El@sBK~oVA;Fl=r~7-xb%M=bMH65Z zVV)T=HHKp4l5TUr)N$&RRmhJ5F`x35t(9eECENRQ3c-3+HQ2d>tl!#5x_Wluog^Ao zpIMRHBK=oorLEtGbb*>KUE;J0M&~S;CYqJ~sG9EzOiy>2P%bslz z`uR>$yx`n$6~O?Yi0C}WxMzcDq<6zo(!P&qUso{9H?|H4Nq{ep_Hnt-$-xr!cv$e` zyA&Lkwc^FYI6uI`R(Iihi`PcNGJ}vR9JaF`v->$Z&6(hPea#KEI5Y1CkTl?c1Dr*; zLs|JvyW=e`m}K2dWb#HMlW=-}k07lVO8L8G=zYmpX?0sf;z9#YkXn1Gr{CyLMxAaM zp=ca5bJ<Q(pCS}GR$lT~TY2~9E2Z$90L0I`5Q0+0lpbN?y=BRt#f`yA3j8i4! zGmZoD3&P6@WA$1LU+7FTM{33O$M(Ri$%e3=^x72nW`v2;M;>HArAUjc6l|ikk#_QQ z=YoewZWVKPT~;zz3~XY6#cyk)l7}ZVd*yB8kZmba^DGYwOnzPItXZe7eL{ir+a_83yg>F2w}#XKDo zp|qi4G`Keh_O?CWAOV20N-{Oxe|g*!rb52nAmFf=lk9D8>@0AY>Dzt7vT9to?3SJy z;E0A*>58bGX>4JpA z8q;R-VPT5NE^Q;-%4e7`xmTwW+0;Q5jF)=H9!0*&`I~s6LbYdr_1~P)R-!*HxQhht8;!=he(V zk63~hKl=M10O=AOGJ>@8vm;apVn;2$7FQA~K5o-Xo;zCB=k!4F^DfbXE06_cu~L~=9#-+e*{-rd z{4Q|i!U0T5u!&`?)>vi+FwH5I!66`<~-RJ^5bNEyb}2@ z>w;6p*4Z??%1k)bj@meF4R!t62iM5~|9ZsA25X;3)YapG-;Rv_V?WJ7Ja(16y>u1j zhM!P!=?JWXttc?^+H_W9d;ed8+|p_1XSmN_R>voqS7vYBbox|1EZ&}y)jmH&OC$pi zKWC4M+QfSCr*@1LiJz}Q;)-;?KC8cl?HB-9^f80YYuL4)zx>4>{rdep@~0PYE^w;# z-OW(aX7@kiNwc6yYZ>9OFP5HD%R_U#OB>W5DYDnUcXkxz}_0M%z02HxB)P zvjib$5{&l`<7(7eo9%~GmqqE0cLB4Wj{y#!T_*22kZdn5s@kAsB%MMgB0v?Mx%9k%~f877wG(Nl=%o4ktB808i4J5za{hhEW)nh07 zYbDr~U1aam5a#a`vq`fNelD_yY8&THs60Pzis)LD3IB1iRQguDo^P8Xvg;G`&I`0I zK$O)kG#L&XzK&N&)YxSS0*5aSa4g0SK1G`yBK)UXF_%i7N2y|#$v{c}f>Qt^cK zlEr`8ezYe%)p8Tlwkl|-?6Kz;b#9LCzH1=EEW$Z@c>`tt?<~NVB}&}!H#7Tp#J=Nc zvR-U$X;YOEgn1FNRz|~{u%W^J6{nhnJ&M&MaQm9<4H`ouCVs)dJqiEU4JbuODZWPN z&y^zBh$!5H-z#(5$8ujTriXD`!ScgZ9S8Em^D-5zH!Ej{7YB#0olj4ekzOxU z{RRkfe`sT8Ip^xxa~=RByFuz}=E0{Jy7M+T>M<&gLZR!;-kS%Gkikb7EVeSB$FePEBt_qYc5r8^iceUd z2n~8eXyGSkLDLE(%3q9^^>21x_p#w|6@Bfj%@&f34K-BO#GYsv zY_W=QxV3Z)G`=wfe>+&%6=ysqqpyaX%*Z<;$dBv&4mzb3Elli`T;R2eZVpg1&SWM` zV|g*r3yK;fK|t}UDkmUyNDU=Uhz~qb|A=k#kv{az@zDpOm^wxIiB}v6KYtI7`*aQ; z`7oY|VW4!n+_=QAVD$)-h{R!Z@md|I9nm`UU@v-If)$N#ge-o>TWloG+&+)7&5Rc2 zNUBad82ak!!wT;vK}s7$c2aD&^xPoa*RU_ZM!iR)LWk&)Cy(fQs?~@GURBq70=TC` zg)m?{yrsUk*SxQ+u9=CHSH@(+IrN4QM$ni$T|86aAlehnk{ z__Yr&2*#h4`S&ODPXvTmm~_mjFd7Mb?V$U5WNx7KM$~}_+bCzm7Dvi;#!Az7ya*0> zA`B*iiPn@Kw+`bdY4`hr6KGe%OC=Iw z29wjIaoW>>!f>=G!M^#D?xx(a-3d)L@uIeS!{ydpfmu(RBVHu`~rl`%zf1~EMU{?lrdOU&4`6o<(_ z5x2HN01toqV~4(wM^Q#n!F5C@+|PIfevG5I^G#lTbge+cn} zJ+qK-U#o?T9?|t^iBr3_Kg=ybTRuv9ccDc8BPnC!ywi17p+<__zm%M1pJPknVAMX( z1>!O}CsKFbh7xHSaZMEbV}|Zdp{HP6X=Jt~pLfodm2qD=rMX<36OUluX+@vup*Y`z zW9rS!liU>f+{lyc#I3)jkpvDpov$oiRKIm;oI!rzBtP}!dX8qSN}+@D7uEExr`D^- zO<`z{+Wex;X1yCl*EruMS39JQ-)cFG5v@*U@L~L~xzN@`BwN$UPlJ>Bw#bo(_cs^Y zH?OUF#w+Mvwf!rQ&(@6Q4*@D16!fIj{`s>oc^>a?kju-4c@Al#FIGv7)c*#e!zP)L zH;NkV%<_4D zvM8@Wen#+7@dsYV7{5|mfi}K|K@*03j~97NW~?|5i{mcZ1AfKupMd&l#I@C|=s2aM zq-6Ffi)xLIGHF7@`sTpwA!U?>vQtv;4KDQ8&lr=ke#7WQal!TX-S)(z=`MfrXT>QS zL-PZ5qn8i0y>&D3CHlEsvxp4d6|~*7lA+b8j#)1G)Xg2dM-+s<-LR2)zIo%BW$)Nl&5%~s@ItCx>dbx&o>~SIIaILdD-bhv<#f`d zQZu$s8IY$Twja^Q5Vdh|Y?PtJ5j^d008PnTw7rJ(3Q2sV729u+Zy1cxEw|jrH&q5n z0ISpM$tSHD^uV%UR1n6>QUghB_}sB0Bth+;Rv5^|Fpsb56H+DC8rng~X=$lt?8<$h zhX?Md?pSbQ=#;WgWhjL-{WiZtfhXe9SZiZQZa=UP=09E<`wbb$ z8f%dWQ6WDer0KW`(=-h%dk9oDXfh*_P^{LI!~liVBpVmN*9!&-=!|K*`<~L1;u#s) zQU>w|F<#M>mG41K3_i~NdV0Q$60dc(Svy}sfO%SNS{Inh8@gujIJ=vX zjf}v{XGH`G3*W!F!xZUjBJO7aY+}^O7YOLIaqXJ0x?+Tx*8#A7=vtKDE z?7y}tzo!%>d_y}sV*_TKBt>PJ)v{|b4VPz53MHd@mbAk_iS>yy;R2!L9(`rOvMNR_ zeeGX!4i*qg&rss)lc*l5I{aP|e2vwG0ZJ!83GzG#DZd}ja8TGQTVz4DZ0c>!ZTB5l zrDAlu=Pf$dlx0@)tb%m}8TC89=FirL^xcM#eKZqVBarNNo&w@F(#uar{8;%Fjeit? zA{)q?BYq{KgFL{tGoQpPHt$TW_BvT%VYU=>V?rgh>FXwJbw?Rt=4YrkGoZ_aLT5RW zEwyScJs1EqyjmxzX9r%p;Y#6up-xfGgf!7MpLz{>im-UHMH_@|dN0x!=RuoiBb zR10=9>2kAnXUSA&WhP2&)Ui-mtL494e2=r|KGY6~-mM|BM9&xQ$fqUWjH{~VW{H55 zA;m!r+v@fzyhDzCW%w&IEtPNtZ$~=#^CBRLlyJcJRiPhG4jlbssTt(5;b)ZZNykLU zHq3fBWtS%{gAUJ|jR`iTPN@ZDjY%-MC8(e-eqt-eIMK8+vcHpf{bc2=Y3ks9LiJ5n z=l=2kHR-ItJ!wzQl@R__0F$rt`R+`41V>ybk84%?Po=0ikft_Yq+k-T$7zdt9w4dj zPg(iFu1d8X-RKEX)a%+46q4cg9 z+yb-SR`LI=_wVpK=*!AF)h3o=jIWSnlNn2Lc&4<1c5uG|`Uh`hAa6!I8C}U=^?)!L z5+8I%597FXUaHbI8)K6p^_zc!=6S|v5&Td@l71!RM2srbb`|8!?uPmLe-+qT&0TBB>pvY2mxRMVE3pmZ( ze-~M)>so{yfzR`elY#I42DLw>#B=gv2)awUKeU=CHt&3+Q4dO7bV{}u52HOnWE6c- zQ`L2L2ddMmQteO0U;mXw*Pf#l4s`FIVT(oPrsZp)3i9n!8LR@a^zd36?#LT~hF%@q zQww0&T;Q*_WpLoIMqrycj&+{oFGt;6x&%~hbu`IM&e@BOP{|`7@?Qe+sTQGEr_q^I zGfzo-S%LLBDdTm4H~Md%=du(6h|z9IshL{iufbn$4?sQB-U-cq`(PgjGhjr+`fvt6+yG9tyt&^G|D-!2MxxhHDB3eGt|NG_ycOx3k-IM`!IBt=E2u;(L)CD?yvgRYs5TAB=9MmrcyfbjRab` z`Sic5Wl~#xsBOe{yt*zfoj_Xdg&i15UfjB*%%<|muNdzq6X|`Fr~(=*ZkYO&-A2_R z85-AA47EbGESaqncvIdb-~?EYN z*4X}%7X1%8JUxnV)TMbGBE&`aY|BJoM}u-kB++bwJ{^!p3xzdzGiC^2jB zaWV)>aatE>IJyn--Ri1@3T4i^HaUB|FZOR{F-6$nxA^_d$``uV+`UFz7!xCkb@*d! z)z<{3igHFogAdKX&|B`TQ~!peUHgw$zfC*ym!Vi*`3UD(n3C`6`B7>Af1p`P#`v~+* zSGjAWpHkYo`|ReCT-Yma)amT7pY3II%+6?2+qeyQAd9)V=&Hv4(8^fJ+~g~&@@RT~ z$kHN`J(L%4kdUo)q45f993VPJ8n>O6#^G=3Z`C8YtSq2PZMXnw;3I8e-Q)dhj;ym3 zcx?IpC>eJDD~@_hc6TV0(|ASfcggxD{g&!Z>M8k(PQgg4SJ-mC2a??{Y)B4@a#3iS zqsPy!#SntgQU)3@7Bj)AW&n0q5Lo}2&2UV9dMP1U#NNjxcx`8HezD@%5j_7!+S62Z zE@7N5yz0hvr5jrl;vJ{LuV6KTpJZsmxA9N4QNNeJ4XtF=&5GMoh zqrccA(J_rF?Fo zM44?9HkU2`GAH`$PUV?5!4HBdUI_f}EWj@lHu-9Goie?mA@b0fe*LoS=3{dcV>4m! zvPu8>#6NOAxvvnsag?64mbM5$Utl zv2Cz_p4A!C30>(-f7X6JzqzUv710-78f>+Gxxjl}_oIEhc%FR7*x$XPZh7S$-R6AS z+&z4yzgI>zskunW(XdOG53RZnuF%frYvmET1p9-%L_Y-YQ_vS&_#S9=Ry`OB3(-Z8 z_E=*(s3oE@$h~V^O0ik}C4#t97B^1C<7;oYHqf66Im=asDiCAvbe1DGy5&v-C zh9VabI0*r{l=l)9b>Zak=*pdIY(E!&0Wmn;0B$O`xaBsOqKnz` zRhj&~Hoc#;#2F%wX)S|tV?PJpYOOMeJ>mXp+MHq^ICj{>^c#)PvOSJH>*wxjvno1mF7 z=x^+@ko8v>mgi?{AorH=&9LI#7(aRC0iVruNev@-*!BDMhF8+PCV5Q@Vz;E0t0KPCZd~t3uTNllcZ42Y)qt zVT6hwg=Z~4~#H8odYGV$q4#O!T;Dsv^{mnAgr8dCuH8=YlLH}%H zDF}1m8D{BaG!a+sjzE7bk|~d%6TOlEe;?e7m=I9nWUUKU9J2;6JM{AT9~qo8+qt%E1p9NW=6KA73h7z*zrc6! ze0n-+!>OV*8Tw{XrDk*g>AQdaiy>dJ$?Nrj;gjQgk{?A{qL>fm(aF5HiB#EJ0|7}7 z9G82e(FmQozVun0UHw-oS5$q6=^acrAKsKkxkrRiLY$V__o`oGvR^l_glsO5&Vy)H zIxOEm1^K*oS=YPUeT5O&i)|=uuwF}aXj_MA>7NgnYEf;o-8|=k+y}CGd(Io0BiZ!} zbjiYW?@2Ku^B`HITeX?^`BBZ~vT>H~^P!FhZO7fs4#(FNX6z2qewcEqA^PDM-{`{( z6b+6&9$z9QW7d`xN*F7}I}R@%6$691G$%8xcFA|0e8VDbKddpp(EZ!eP2HI)nnFME zWLh{XqTt|YBJSFJF8_}&S9R47Zj_~gnQzZ+6EEM^33VQ^j|=C2(exI6QGW09@X{jP z3rjcB-7ON5qI7pR5=(cd(t?PTG)TkJ9ShRk4NET#58wCa`TYy`>)dnB%r)0cJyX*o z4PU6N1dH;C>;@~@#)(Fw*!72qpS9w%ipPQ!B0%QZ@%~+i6w^;%N8MG!ZRi58%kMuY z4@%9wSM?7FVVsGPLwZ8W=F%esSt4?Iee-ox`|`P@NcUN?SV|D2`d46jd8&Brvrfd0 z4d8hFnm&ku6Kd;J_wu*VoyLoSPFoTq4qJDR1J^43V4Ei8hzB#&q>rJb)H&kz7*6Sg zPCRQhU3xg($a}r61yXE0b%!Jb2A#v?@fR3~K3RoV0qMOzoPHJ2N_WuzNIy1O*VI<> zci3f&pZ%L2X01T0rW4=D^w7B&-hDO(VjEnCjcPYR5PJ30Gla^)wO>QOzgvC}8h;y} z62E1gc<-sZ4QPbBYHZiwAGzZPGS16qWBXu1vbFqWbp68Xg$9XHjl}kYzFr{OK+D^l zsXxS2k&xD9<952Iwf>dK-3XU(F8}DTq{a$N{l1G5Kzx)NR(q}(bi(Ncz;as|`#6f; zvxg5B+D7tHb;10(Ttht~HpDuH0^aSm^W%bltE=cN{--c}GoaGEQFn8R?!Cn{wOUA? z-aXz&NfmvRvN+eXJ2SsL!r_Rg?QsjE-fKmkfZqLw21j2JZ`>an1Da3mByWf$U!Zlq zP~>v5$L0^6zvHA`PQ02Qi@9>lBDdR7zZJD^CzPJIG#)Sm5leZcipEhx2d$X7#)YGoV zOSx0#Z6c79O7pZ!h1=+{C?v5plQs?S=^qNY0(!G}anCDu!9*R1o#v`vsf#;*k*@Er zkyxXWEcdp>yD3VR+F}O)cg228E2c$ey?+iq6l-`m3zvs^Ba(Q7rDA|uZg9VvYE0$~ zXqzxo7ngcBj}NPi$$6Wr$pg8%lt8h;IVf;$ad6I>p`avP1F?Bar2_?dV($lKLPlskVNJ{0#Wfc}HvV6aw|+ zMAV}Sz>Qm+ibcrDT;(Kt{~0MHa}eF@tePu6Utk%Ca257(xD)TEUTo_Mc(SRvFW)ZR zg?P(0sU2I(v%27)1bPYU^x+Cz>&z{m|2O2zn2*K^Q4Ol%)2385vX7L`sCj1`6!D^6 z*g2|sj{n;Bm+C(u^x4|<`+V8Wd)zZPIfaY;VD4`kbuPpt%&=%4V{S!sJ19wkdA(d;9{%fwa=b zG0Q`&f{02$+_)j4PoZD&4>btsO4ba1^-Y{U@3ZD+Tex|2qz#p&e@ykYzt^mL)5b9C zKbT9{rJV^!mofRn6{G9E!dZDsZ$BXdtcdFnn1tl;)Cv4*h5QuXQRed=n@IpZ~Wvyme!$`~tng-Y{g(Bj%) z8V#{|7H1#j#lGJ*61O#nTwqGl$S$-Q`n+iotkR=3oy4n~MHMa<%!Jxkd}77;kV_+< zyzhGZS=98^gkRCVSrl*6RM#Tod1a{^7-^5E>q8;pWWf=yw*rD1MMP?-Qwx4dg^z9w zNE2QneR`Jf-z7@*{WIqrHM~hg(iLh;>z(OoZdKW^nF>c;h@CLNpAosRa90~Ch{u877LFSXtYn^QzYldnn6`s_U@!@ub$=_XzzLwOv zi3XFLQ}hevGa~-vMIMVYm)SnChzjVeRxCwUKfg_87QsR|v#UCKB$< zi+mT>)gn9Qohg!^JL8m=B(|uv3){@;&ZHxz?}FaHFIn=)N8;m6pqXzDZbt-$>W-Wu z9|r#KHjykNxOMl#JA-$wO2&ev2V1)zq$dN15HU5hu(&<3L9d ztdu}`MM57Zj2OLpUCoxH0${;K6*8*p6 z&&1MZ%UVxRzETTxa>W>hMtvGtai*%zgxEQtB3RI!eF0$ox>j|DvSXV#j>lyk_~^05 z=H<6~2ph&d7a2r_DIV!we$e)u1w_}6N zvz5O+xzY6hq1hrXqLsAU?mCTl4p?iG z2wg-}M;?GOktG2=zy6*Jd248d;$m+sn=0w_GF1-ae#ofMaP)HK2FeMcEAOrr_=y#t zpXjgq&T?g4g$hIu#ychIA=zbFe;y)TA0WFQABsp3FPUyTDI`a@oQ^R(7@6!4c)pYg z<&{>o6-L~byw1aY{vYt=ZJ|H*J6k=SOLnz)8lH)Dc*(jY`_%pG`hnVi(knt;cWq)9 zpQ+s$Q^z$HoZ^x`G{{?`n1fFHvFn&VtuIhiFDhY%^SwPoMeItevn2z9Qe;F>Gn2$g zy~YG;yZRPv%Cpex!2w&fRz#E59{HC%pn~7T-Qj6HQsekQ7BUzh(ftFd5&Y{?0eIxi zGm4PqilA-ILvmsImU(AYA-Dm)vV4Wl{J4`6CMC}Ch0ZuAf7MI73ERwd}oMIe<;=` z1LFmveWZj2JE4Ku?o6A^@E&sdX^k&MZ+3TnW&(~00)+zJFqKBS9kbaEY9c@M(35an zBK?s??z>0os^Q}II+9pkRS1OO_F3-uM3PyDIR0M>Zz9+9AI0js+YGSkKj27Mo1Zwx zSH3o$KVuolV7JYDo8#91rv<>v(TP!=_+I5^gtMx>=cf_E)n!K#7jDw?)8SwD%MfgW z1$;s=IK=e^kwrF*wrE;lCkF=wiQAN$iMU4l1z;jE@V_4zj{H0?Imq7C*Nt%HbY|2U zkY_}4-*4;{tMID|cnMP+pl3X(<#rksWykyl&0SSNLIS#XknCp{XpxDITvu`UfjgzbvT@&xV?W3}~%lVIhNG=iFqI96H=lZ~6-1A=FK(TXu=I#r&ukmo(S4NXvTG#)0 zHTIsIy5XyznJuqEb>y3`>lyY1<zvQa)>2 zW}H~=jy_z6FmarVD?W$nHA$8%R#P$Y!SBTHexlo!HYmJDot7YSoTt_+mT=&n&eRmI z?wv8^w7RN`ce^E$I&5A38EJwKC6;%MkHHg6V1a*2(7$3tS6z32-I`-yb6V@T*WN-s zv3;jS?p1~&bE?%&NJn3{4P@|Zs27fo4Et`KJZ* zrr3+9MIyFd9h^(f&2S}v_nY%#8BCzNLNdcr*gs%dL6D(tSqtg0j;J{*_J(EHllwRM z(xpXU0psO=FTI_s&}krUh67Sx#w@jED+BZih% z459KHMv(3Pso0U92R8XpI0*N@W9MQ)y@3&UH;Ex1(SNg2M3lG{O~Q7!CeBC2ADq<{ z-Xc5nas3roi0$XLL~^UH>B@P8cajsCecXN-cVX3_7Jt8wjxqIWWdJ*9VTSwfVEUdb z?K#H5_o@J5;c9nc!Fi|XkCT_q2re|EE}23P@nk{8-7EPblyk&ddz-#pTu~WiS56|; z68RREI9Ka`=^Ji{oxY(LCY!yMx`Yu0v)D>qeS;NqbI6xh?59-uA_w}7W3=tGX9^B~ zKg8CDiyTANSU+x>a#T7K%Dgjgvn<^u8h))q$z!IC3K>!qXEg>G|6}VL4e&Mk8nQpdP ziyJ}6EIzR_Eh|187kt~vTjSK3*~ax50qS$x6@eF-bRU|;ha}_j4X}RklklGoLVwcV z85sY%34PseQW+!0%V<`sb~0%#8piV4iMeM;iX|W&s7iP)gh_J}E@TzrzSda*I^*)C z#6P1VU-I^+9B+AhB_54~ti<@lDg}Br_>ZIoL@;$$0j#{8U?``l8%~|zq73y@453A% zfWBg_-Zt~z4@{U%W^?U&3A$W7gr29FM59XQe42GUm8?IbN8*hPjt$F6(1bU){$at# zPd0in75QmDgUnGe*c0ll{gdSueb(BXS3ioa(~Bf?wWRkQ)^)NHh`)xyUKPcE{16h0 z`9WlO=zPe2>_g}Dw4~OX5sTP(v1L>NtKl^C4n*p1a<3Jex$m6ZnTzPIPj-$FnZMJc zN>f_+7COCF-6p1H$LKcV%zTYBqU?-`k05&$=EDO@+$eh_FEV{%b(g>TBg|LQ4T`k= zf3Z;?M<|4`)J82;UcSh3%eDC0WQu#x@c0x!V}!ZW^6>TKc`6ik8$kzAU=PQf+d{O zZn*7B-iSue&4i6u{^Jg<_!4*x;_A`)HHlr|g&}gGI{dYfck}Jf=3l#mR5ySoA;R_g zkJ)uih8s3-Hf>{ zd-h_iEJQ^>cDnfevK!-h=AJ}$U*~6JOs#MloO;<^yDy=XV*=3_5dO=V4A6+zoho?w zIEm3}11QzL+l8w!qz zvM8wFc&YTzBGAbcFJF{{?UZkI+XcjI*r~LI3b40&RjL4~t`F6Y!p2>EqtOCP1_556wy@78^h914lWH3_qr^n`ax|6|L8Z_od zG4k#)Shk*!X%{m0HPF#sIo@MmlX^$BLA60Zafmb}8O`HwNX#%GjBGfBs3noMinVmkC`w+Ot5hup%2i1;yQEm z-l4vwYT5-os7tbtqee7GaGQSm$rYJORKtc~X&MlnAsmw+dippi&N-o!BVkP7(k(UA z7jrHY#hc2pAiH{9FMag2t64M8TTt#u)w~Cdw!KACjbVCjYkmiV7QR)-W@KO>p~HC6 zCj~!?lMH<9fNr`!y<+1N`s)Y)j5;D3-Wr1b*Vpry;mfLG+06t*uba7F4R5+>ExXa` zwA8R^XpZpo$6rXgUCFw|`C5{8BRrM!uMYBb2K2FoMHrb=?DMeas%r=CJFodmhNIOo z7tpg^$Iu0GGJ({|g>W)5ofnXI?|x>xM87n9zYBj(K6`KDR$}5tAt;w-dbe~VnMlU_ z)cr8y=Dq^~5naDm+}rLb)Qq$r}sjI$Uc>O-N#1nSjeuA@Ctt83qpp4QSPK= z9sj0j84rer;-xAd+v2u1vq?<*M|k=&VNI58n;@ z#37K#Jq%m8pB+r*EVXj}d;$QWO9FyRKu1#uGE*g!-8(LHywt(NR%q{OtU9-m; zazCn(B-hCnthwQB5%a*6 zO(hyF$}}-BU=Qd};9;x`7{sAgD!fFQfqxav2IpoL*PJFxogZozJm9T4(beL*xyEma zX&U9B_s)BHN|k1#0JQ`)_u?qFMAZcrar-uARuu;<2J~b-stGCI9L2*wFW}ip7lb#d z)yOtTe-b5e9*H0U7#xiCMBcbkOJ!wDjTL}I^e7)@_7;g%3uapU*Tv{H9c_iCaeNqx$muo;+S z$cT@cq?tB5_Iy}a?EEbZFW&zdi97}ij5SnY%XdQeiQt!yv-q;^peR3u{tc~o#j*Mv z3FR$hm3Wb*fiG&FfKz+Q)%Z7Q*#StF?>k9OUpDls?f^A|H@9IGX1TpH7Rk7i1D)5k z>HHA0uBP|mKrQqhoY`MdvyWiiGxm7lVtLZ}dFUoovsmEK-Z`R`Qyt9bX4w)h%!?M< z-J40#!&67u+l8|jlNEjZ3omzYTpQ^x=on|8#dSE7Tk<^a1G%#y{`!xsQ&nlMK2mS=tt$YcvR5hBOxJ|61=t&z9J*sP1Eb2RRaj*|#5 zB{Uy@cVRNbiH!4-7%Y+s^*r_{kDm#6H@8Hjb;5Bh|5YWkX(bX7o$txdIU^YOo^;i& zD*rU8^{9pp%EA=VuVkKF5Eg7@#h2ow7L@dwOe?!Qx`tVckBzXVov zvkO{t+UBen77?E7xj}bzbU7s4LgT?V7w=Pws@q&D6mPV}RrH7mk99O2Mx~BrV+?Yn zP2M7Zf@KI=1IFa839R>;8sBg-w%f6+$oJgOSPNfK6w^W{70%;f-@dnMZ-Fcfo3>F_ zQ2z#tG^!v|cJ6f`bkg{Z|0k8^IHMMM5#AtAX_CUIxWB=OIdNem&ILc)Np1|M0fWzq zH9n%)&xG^g*%+7$w$aNpvgpYgjF@Q~*nMkY1kaFHy4olR3SX!KlT!&Q36rVY<=u`V z(Puy@3HmFy552~b@?E`=GgJNY1&?N15xAP(r#8LA%_(5VvCWluga>1ZZMRrYXe;%R zbnv(~sjhil5h|6un`+_L9hZpgBmn>j8QKRB3RXuOkRuVDfOPXEqcFw<&9eENwq%R5 zNzZY!{#C)=F%~NGZm#8fZ?k!s_pjSTz`!JNrrPo{Nj4>(zGw}MBw>Y^Rm%pvNa!Mo zZk$SGJWB{BABx;{d+0+g8ZT}p@(wee$Y_r1EjI%8C9+Y>#AwJlu|Y(ma~{kPSs~Cw zv<{>&?4|LK<}~0R$*sYwN_vSL0AX^0ke=mULe8mu;G{ZS}G3?98vPhcn|H8EoG#2!K*10R5!W1FGi!=Cau>#IAbT@FSo@PK)t?J3x*`O zcM$(0vuS45P1D5Tb~JJOYIy=^h}6yCnF~hiU|fnB>YjVQ^43yA|DwJy4(LDHv(x5k z6_*k(L8KqZrp{4g=fnDNSES(f6yDrT0zhc#;(F6`u|k4#4yf$7yrN|mcFpH)`Tw+le@HHBb<^=)c%*C=nl(Sj z8SUI7Yg4P|-Xmvnt$R2tXW=i_Vs!DSlU^LAOPahrRCTGF-=wu@b6pKle-L9k7h|eu zo8zY73Ew`z!t+_Q%nfSd7i;An@InQ~%( z3M#x&!LR>UHqa+pbTh^SjC4KyWhiSO%UzK_oS>3FS!MZ6WFUZr)yZJQ5!3@*CAV+= zOA=SGv-v|<{#4`vviz_xvWxx0f!nNG`JUni7u~aQoD||r?#|F(VF|0Wb}+#G+o#@7 z2*&+`wRLC_UV%HfU~cAtLUfaHx%}%OqpthlsKy^Wc|rm}g6DE2V_M=mE^9PS8#!#7 z&A2%D$=~StWfNxg{x<1f(V89}ZC*1W)?Z(xH;2Z~(tH8stD%GW z5DQ_gP)TI$nqn6k9n+iC0UqbR3|gO+)0&`feYtjU^>&NZQOE4fOJGJ)iL1qn zTx|aQ``oh=#Rt59tLKX<8M^_`$m_zTYFn>|Z##{ z1?4vLw>VrN;{EUOQbW;|p|`?YE5!c)Y+aN*PN=EwYc%m+!ACK zlek^mrVQHW+5}Tn-Ld@+=NYB({8N!7N*#5vJL&CMZO|;nKmU`d%Fyd2Xmq3fZQm56 ziq&mdllxaxX`}KCGRMMUwRYd&@Ev;RFZm#S1$JGm$9@tD8hplnG_@79z64OonguP= zxfjE{j@oB1<4-o9cmyAxr4;bS?ycrqnO6rS6AmJ8D}{P)a#7*uRh$@`n$~6CXB>|> zM-JneLOGqtPn>~LqZ)eVQ?EN5apV17ve&0P+r|%vv6=3D8Bh;%?btvy>SuLwZ%t_8 zQ^RF*KyK$A`lEwdQ0w|C(JKFWf-gtRZy=EfL13%ZZWG5?U|S!oQ|d+O^tahR%y^Sl$dtWs9hD&Ntfs|5J{ zKNBDj?RNU@F7u_xj{f;Cz0I>NM@Ti%t>TeGr$V~XI|XB5 z%KX@jQLVrBOuD$jJ7F4!+~>}@&*r^Q0aTCO|NA(%N1guKF0L-*s{|#-_SXNpD1KG$ zxhWtWJgLrU>p_t%#=WXDz_lvEHvew?OI1D_bop65xqguu?&a38+gWhFN|?VaJ<48@ zZv3_Cw=$RDB1?tjd4vr%LFz4iB6{b!$VpS(^S{e~5>;|8*7T0@G}c66uyxC3l`djO?Ge{X81b z-Gyk{KExgQGf&7qs9g_qAgPNvLQ-g5rzR<-pOSST`(w3)MiATKJI})SQccJNlQrL9 zD&4~F1T0qRHm2kL|DfsrE=hzJ;-I-9<)-%;%XF2?bixHU=r<{UW%wDTj6N@Oq0p+u zDcEwDAzvt@_>-uR69A3b>S|plPjDDDwEU-K=Gpggnz%9!V-htV)~9}-U?Mya{#jpZ zCiMoY#Sgsks5`MXo${_;+x)P!L{G8`wM4Fc(%#^7EBzDzq6PG4olv6vB)|I6YIU*h z@S#s=^beL+UfyB}O`R#7X9p-bnzh#WR?NH;LcNY;^Ceq;DF=jsgGv3SiltvwnN1)) zuwZv4x6+XEn2;<$G#|*Peduq({nl$Sq1IeW`nHq8H!EAAdz2-vy*b+S1br*)x-@B; zDa5MCymiiEiRU0xN`p8S8=}aJyIFp#9EV}XGZ2qja0%ST@h($CI+i1KV1(2DA@YFh zFmKDg+)_a<_~j1P9>QP#_d1hM3nFNGaj!lQ7hYyHPNLal-XLSAuaIfC${9rIzn0|g8g+K)-ytTT@I`4}AUm9?B9x0?_eFBPl`>hd<}i#@Uo_F$ zz4%CP=LEcVjoU)S%DyQ>m5Q%up0%I{A0qQoWmx~vVG=|rEtr~Er6o?@tqm~jW= z?mV2B63`~z>kSdbGt#MuR=u(+3*sR-I>r}~4D7jo}7 zJDaaN&I-3R&}$|$`I8)W0*?BDbsZj)%9pA`^4+?V%6koO0T|ToB}%4_Hu?)c4vPrY z#RIn}U&p}w0mB$aS2*ws?Ke;wGPBUP`k7NML0HdhN|4S+)NLE4kcqn?fR>?nJUn$9 zUUUBQme!JKi>no(W$ImT-9It!6=%|Nxx__%Ml5pcKQ}%$PHWZ^W$J1bpR!cZGhxNk zX&&L;K465x4&Ccz3;;N3PCFk-h?;qqdVHmWIMU@?O?dos#oC9!|Gjmg1VT(_@&V0Q zm62pK%XBu*@n-FVwa%c<9YMK`h~Ur|FTEXuu=YCDa#vSrxok3{+PRq`J=)y4eF+A< z9SJ@j`G>yl43qKiq%3#|1x>Nz-^YX#J-X&Q5*$v@wT`g3Zn(=PY6Be$UE@@`=KY=0 z{qUw&Mp|SNfjya*${9b*5#@%d;=A#zB1L|iEs{{&eL?CPQN~pm z5nLOAC9pat?M4%K$U$QZ&%Xa{3jmIu-XW?FS~Ietl{%)zcst4N?{ww1@1h>!^f8X1 zBVlsNuIvISLZlAz&#-<(EZ1TogU>K10G(l!J=Ml38ul zZdp35hi&C~zx}t9y|lHPtKnMz_V^UhLjhc(MmAm)CA5eGI+~^rQespP2E_oMN35)fX@!~LKD4&q{f&GVE8WfUPE+FJQWczNYj}J!ng+`L zRob86YT;oP9o}StFRZACVL-xX*Oyb~-p@W%87;gQCm)$5SV^q8eK>IbTF>Yy`9GP{ zIskD`8vteT*1dAta6)PGQa@#RbO>6qGWG506m?btjF-D}?zl7x_%tOj#vTLRIUQ6^ zMNcO`py?5#Pk#X2h?m|&4nV}rtlZ-%*k(*uQd$n9eLsIW;+*k+L~Tr5GCvZq30L83 za3$ln!V3E=9`nReoH}JU?VmVTopj4vlyox8elGBPcO(hpW^OhyN9zR{ zd{{N~rPr`L#g`2VtFzp*LE@#UR;}!($=*c6^9nqyc>z`iZN!yp9xrsblDK8gUgSFJ zHkp^GhGdH}f)n59Df@?Z*|1*^%XmWE?QqW0T41sji`}>@*thhP!?^Z$X_tbnx>4oQo9wdN$tK_IfJ{$d-lFU(yZzWPx zc235Iy7+~ZZHlxxDrQ21yU1EX_WUs*`Ef^ zLoYX>8+DriUl_fAwa^El#9wT`GS}{-M-$Erz{hc0LXf(h8(EyrxOZK4uq5u^P$$|9 zxH8)@zU;6Lf!{e@9%(eIzfH%3Gmo^Dh+m1toW%NDq-;{!gHF>~+_;I!WL>=vUB9uGg>&iBI~zAaxM;GL1VdC!KLZxV+uv&)9&8 zQI2SwA7Hg=JNk$LoEM5# zd9j&bl75mA(_P4+RcwHg09b#Yn;{QUOK3uo<+4r41$c!vV<5La^rO-_c5?c{aLfg| zpr5TIMTv2aRYK_lY0F5ASQ)`wi0Y0DLPm`bugT#eK61{M1_!+kS(WF?bNrREBWd zRccdL2ya{9KXAe|zb)Fmq(a=Jm)QHy8sLujh}^mKTf$4h8S~UIXajckEWJ_qM`Cu? zBr-eUoTpo+r^{P~+Wuoxv()mR^lrnC;|X}C5O+b0q=nzb2NX38FYAjDr3}uII@)@3 z5BvkDE0;)k3Tt-R#WND~(;fx+ANW6>enIRp1bK+8!i^DQaV_krX=mG7nuTD6COmuF z7DwL`tTA5aTGIYTu{U~*aU*oTO0Sy95|`INqqDiYO4g5ZZ}0D0BXio$q*LDR2A)iI zOG_e7zZUifEZv2xr7|e$8d!YkDuZoUGbDxfetnDaX?(Nj)LTw5AUmsp%&3-=W3f|0 zzsNL>V7k)-OaKJKL*_;ZZ;<$m>DxDQN^5ARXTCz021Z$UwqG|gv)lU0Y>e{a=gsY@ z-2}xZpC73ZT$%GO|MR4HB6gf(IHhd4>Bgn2tq`3OIbm<=VSEGoRu@~Hf~y$BI3yXl zQ@CQ<*y%G?*D;8HEh4ooWxtgfv&PAg4QwBIo7-X%_Vw+`Y{PAhqYbLbdMFm0{Od%$ z^#z&c^p|5hM-dr{u#}Z71F#;cnKeG}kBb5zCtE;g`ny=qa#yzCW2j0;7|XS(m*0f+ zIQiwlK@&3`JYXb|e7nuln{Rl0aVLL0D@)Yo@jl&MmV`=3B1-6hnHCsoS)7xsRK>%W z@A{fN0J)uWt#R{4sCPDah&d;Lg%adfwR4Z<7)&&!`<-Yf7+tLMJ;i8LB@=y&a5X=i z)ekyNee`OK7QACOdCu0qG^_ZyCU~-$0^#6-EF2PS_iyDvo0F{C@)vj|Mj zZOG_6Q5n6VuEBAOnr*&~gtY4?R}aLORal>7%Gso7GQ|xYiiF359R58FO$aeAG0^Dc}8fnM`!>3#-B6^J}^GETQ1i%_NA zd+hY7 z+3Es}BEas=@Hy709k=_k^n>AQO{?)`iOwp@QT6(%P-3@xkXS12;Pee9U+p0Se53Yt(1Nxvss0u6L< zegak?L^OY#z70kh2S7{1@3Ln7eV%aNL33)@m_h;y0NCGA-_THf09?dv=)N&rYjS%k zQ&eeD=W)nL+!D8rf}(f)jk_jJ?pzJ{W&dojy>|D)__AsIRCEz;eCqcxGw`V@aB45R z<9Y6aJrCNxe3=bN$UT7WxNl4BIj;m_CFxrfdJQzWt?kAcDYA`*mY8%&rjhDnGggWT zZ@x9*hP}scGH$N3TJzF*e>1)MP4N!&yefj$e2UaT;?=#&G~dz`zQ6vhMC9Az>;5N= z{o$=f@u_BqU_*-_LuVnc7Aonmu;mCG&yXSgcNo{ z2y!kFamLw2RKoZ3r6Adu6T2qCTf3hGa})Bd1X-ZPx3(xlUDn>&14=1Fz9g6ps$(cqx^PXzu-8`^;FIqfB~Y#na54rw^1fJH ztUW^mc<(MGUz^ci9`pl`vWFiNUk;q%e&Qo9Fv)Y3Jm}@)MaKh`|C05Uc|RxRB`;aW z-Hl7tG038+quo&p;^Ke&U{mc&w$=W(;JWKU#XxgU2Dbsr-@I}M*li-9My?CP-d%}p zWr9R_b==!8i2A*kJob{sSF4aoxgt6}sM=y^Cq6yi5N;%v{O5)m_&$)$mu3 zTg}_I@_okc^4tFHFMvG&Z|mwhSRy`Ef9Z8jHeUb6<$Bq#-;Q+w%Q^;(`xnMwt(o3%Ao+Lc+DYs@VJ?J%MKRb49#M)9nrVC8eiSDy&e2qUbKE(jL;6A$89|1r5QGeYyUAgj^05>v@+3ePR1F9 zK{8vWTA65Q-0>mk+rlUUp*U9Pn~1#(=J@5EF2X9xCk`U@?;KUg5VU9W2YAq9@W3f3j(>_HRi zRZzT{%&|Z0-SF`V3pJ;-Q)`H-CE*&+&XTDcdJmx%Q79%d;aYkFjK13Z1K+HE~9=Y~Y%ppkNAS(e-|*I$3IDYs zTHY{{wj+_U?fmA?cy&7I{HQQ@$lM}hP0m9T!V^3N#|0>X^rs14c_6~=Nao=aU16w} z&}&-i5(ui((hvH{4zC|%!t(y4(kr&jJ@ zcRtAP3NKU+{U~wuu4I4H(CqxVRKpNOHfT<5pZI(-Lz33jeqSmHQhy4AS87ks|gM_cR93A~kjauo1g>q{)~dYM~* zJ0qU?t@4)mXL~#DlQ(l$;nP%BSxB2jXc(usJ+-0O`xg7B^Cf1NouV~K(MYhB9Ao(7 z`#43x#NQD1Ths+5-k|*0SA$J_I@5s9u{oSteGNpZE?@I!fM9TABpN^d1pr)cYU_tK zC3(>N@-@P`AiY^5H^^MYO^Z)RjmLJA2=||CmOs}1n-CU!+$l2YS;)-)OHvI=r4>Mm z;{9v{=e~tSK4Y_`IJnXNK|YH8Xqk)|q=H%d%+ZqH|1VeflpFwxh;MG;Mm0U*j&^IB zj4OCP7NcZ4o{{B&b8KEA^SWh4P{l2!!$ov}bV04a7?k;^>0m~<=gFSZy#2@P}Chz!2lA$B%*h=S&Fx z`^J}rYviK=3NWflDh@2a<36mA@2k@D2&p=Gu~vZXs4-LmK3-7X{i->_)l)yu{RkLC zS%0ChJ(h$}>@aoNi1GIA@Ha~*pwJeGvB*7{lLAXzjQLT+T#MFcH>PIglYYFX1 zEAdH~A*waaI8hQVkPmVEkdA@48cv@`@g_LHgQ#tidfRC6I3*~OM(g2T0*7|sV#Oh4 z#=UFMK8Fx+CVms0S;F=&CjH?R-0FunIeL|ttpAg#fVDK z^7T$K@&zX-FerB5InDif^~L28y|Zz7sy!g)^tts^?TjGkF~5W9`CaEzN9nC*P~Lhm z+u9ZB%JJjf&sBo^W$sm`cb?}W$cYj$tm7c&X?*XQz=?1NNTH^Pqf5-jNb22ckWpeJ0(P5{?OHHigQ-=_=`l`X;YM%1o zaT2yHn5WsDZxn&?bAC_1vVyx$h=;oI;*A5GG-IdB)ah-RpSj)gx3sxx`7O?{cS)HK z7y$H+IZ*EJCTeBnkLT4|qJ|lPI6Bzv_(VIlH6j~Xiou^;56l`ASg8pxzs#8dd2vw< z^5$VPl;f0PK?FAXTp8xM!cn76n9nw#KEah+K4A*puIwffdrh0PAqc?-5?-&3i~m;5fUJtX<~}&f2x)DeJ|p!XVA2=1x^j`zdWa299h4j zu=J)H0CJu>mUqj$<~>liqIUKW=w&3?MTP9K#u>P~^zw}Xa`(`v=&(Mg`-s-vr2We! zQKiXYqNQEttgkH*aqzv0PLjnDm?;?pp^B^gxaNFSC1cfRWK&cJ#$EQ6l2ud6PQ@;p zwWvugb?tn1Z4&FW73|-r)@44IH~3>QBign1IZs?Mqnvym_aOFyAW~?& zKm1KJnu^^gL{&KRhj8=^Y}XSQ6G~ntEAgz>hLD%Px0E`PE_UNZL6&`)*vIR-Q%|gBgM$p!-l^FLLDu3A zePJRB4JGS*RxkG{%Askqh#s35k#e^zLC*76ur2K$3=H?>Hd<#eUO$(}T{f6fq>rsrL0=f-z|Ze@l0;8jgXFFBLCgB2~riPw_9=huI_dpum&t(*-P_%NLgCa=Dx5k1rPYQ$Zpf5wRVV z+p6dH`%hi%n})NZ;R6&LX^RZ>?OJwKj!em%ucQ9^WhvC!fuB;%u{t%y!oX!$OFOMN z1MEUF(;TC^FN##WYtv70%2SI z-Oi92CMfXiWK_%fXsnR0#Fg#-B6xS(69*pBSx3K12nOeIg)4_F$jW!6O5!ItI*yLV z-Y@~YWa$_kX>kZx^9Q0ruo#QuCzjVic$&_ce@HJYiX_}VPgTa7i>IP4VP20lHca=c zjV-$DOh&NCP+43#(Jl{^iG%hN*C@|n(#@Sg$5Fr& z0!$p4;3Rs6$wL`kC}Z}LiY}}FO%3$twoWZ$Y-Y)LGAmb;&AYz)uF5x4_S_D8%Tlok z>XaoB!0u(AhjsyL2M1AJr!Ye~8GA;zV}^wOlmQ$yj|F!M7Sx>OQlJ)N%y{}^pxUrl$<^~NebDF=+J|X zB=qdl{kmQCzSec{B%|tG)(4$$C45Kq7Xq27PK`x+hg|RB*3loAX z{x~JU&G=jQluC=qON+t~tbgvq+C9ANe1>bp2s={K9pJ^h{p$1l^~@Le_}y&z_fvoR<~w(T_w3qk>G0;b;@VmB`ko;cIJ9s5ov?i6d4&ty zB7#|=TKgzKl;|F=e74F-Q#>1e@RC7#jK`&wSSGv9sn=qtrZ`N~v}{5KscZl#WPd%B6uRm#DFzuH|XbjK7vOaw8T4_i5LT}IAhyC^C zJY*TnX5;}v`y9Ns7oCiWijHH~G;_;9(wS);?axAWVSV4H42XKRBcz&fq*4i{S9jU# ztXizHZgo&Z_KqvYf}P zr#EK~3;}&RTiNc9>hB?McrQI-@fV}nuWZGBxH@9w+t(9quCE^Ypk6ex9f=a zk$$V!PcPL}uSPU`oEN9fcSEaPceoStsVkgs{(w+x6{wf9swcl{67E->FHhp*dK&*{ml;qdrXRyCT$KzbGp>m&%o(WrFOUZJH3# zdX|Yaa4zEaw?EEcPVnQ{tXNI((Yj-~=<@VusY*to#n7O`^~Gh!b}foFHp0_`v6}3)Z38}COkMmy2Zx zn#cwP(E>IQ)1OIF$W^`UKdnVl5C%`CU0v6HMZQ5gdat4mjEje?ow2C3Fp!O@Yh-Sk zXRZR4k!GQ)dikdc&WsCyLZY85i_@p~S#7od3}YcHol6l*5iNFUd4Zjm)m3chHqm#& zmkE-`A*|`I8fr)!mYGO-FKV6L+2B{@=Y_pCLVxNLq^t{=?lYO}v%|WqEq9pXqZF|Ii-s@pevfz$aDguzG?vOYEjy8+eWzYw<@gI2vlq{Q)${t2IcVVmU7RnnuA##! zi0ff{skBSv-|&P|?@Rs?bJQe8nUk0usbl;>cY&Qaz^y;CaXI1hbR_*6zBHxmY-(FA zY&~JEkibm<>!k{FAsM)o4vaB{LfHS#H2$gIw@y&9v8MehMZ|&z^K@ui*DYQCQfdgK zH~5onCCSteTTz)?%M@XJn@36~X@4?&POFb{_$u`5A|y;9aM%nW6wnPpQ73{aD(wqB z_*by5+42xHI7aN8Ey^4sTTt{XFLlwBnR|hPv!&1`9%j8}YBb|8IR&g+1|%+CNq?0! zCuUga1mPpkd@s=lwtn(hRHy6DLEz!@6A%pZ!JrSaOet9lxm#O&*p3jpztb0sonYZ_4PC(^|y(wfDxjdHBGAXXgLeW_FJIJU`-R&wB zzOWBCv+(o!j<(5E5SCv$tfN?s)XKX`jxN%}WYIuht*blZo4{C^n%Bfx?Db>1aDOLT zyj+R=;Ep}B)e$aEhfVVO2RuCeCrTbL4>&G)^VUeGSOl&TwMY?GC_gUAvuVilQe7^pCUud8EywIe%TtXS3n{Gw{h5l>Ia2?8zLXjRn_X*DH;gE z`(WUAcxX>CSrbPSd2;x($tX;GFj@7Ae0W&H@M>aNfAoh?J%g?c#kSnvCf>l=Z$fXN z7uJBRjGlO-tQ~h)c6awT>28J-cerbk&6WuQ=T3IRRj&Sb4@TU#3JQomSlVk~L#N|W zU%p;SxJXVsM9^&#ZjaD0)d~Q?av@Y*J9f)S?S8#sflj!OWFG-#_A-E!)14qJKNu zIrtRV)!@p0pj`#a1G01OrN!mgI>mAL2Mns)p#8Hk@PTMUQc_4R6~8m~awR}8;ftNN zDTJL2rN&g;pcBLcfsE^;K`^U~$yj1nNIRukUvP>cRV+k!9(V1`*dE9g=M&5HQGh^v1EOjy6m1grxi+#|ajT z5Q1HxAgjKWLNR3KGe=I?!_XqHGgA}FPrpo`$1Ok``PeG7=dXvIwhnD|7H1bi5urqU z**4B%-<^X5JTe-T5EFDnjSI~EM3Hggyx~VnLJ6Z}<8HJ2ROTxZDqn@?V61%r`H(z7 z1v@`P>5>o!$MVMxU2yF>>laUbQ*pior43}e@n8(c($JbVY85ddavy7oSk@LHt%O1u zzZsTYl%AqVw^pyDqQq*{Fa>XjWgu9K%tZGCg=2Z6!nCS4iztp2RpXzi*cxob0=r#2 z8?y7HOFh7w!~5X4F|m*x_w3{St6R%Q3cz08BG(IVH&@r=4VKt!7owx{Kzxo5gZNVt zwU2^F92#4Za5le;u)8o&*jrdNDEHJmsGo4c^kEP)@;WCsA3Drk#}u1_+=o(D#@SFr z&-&F+;zLA!vPHY;T>91OQ?wWxA=Hsw)&zVSa&JJUINd|BJjk9XAY41^vt;~#msYo? zm52g@%Erh)g9KU^*Q5Pn0y|XTZ!EMnh`Nr`OUI&4wWbP7D2;QaqEI zuLSK@F!eRVx0Ht8uLM3cI?#QLJTEVS&7J8iTSh8nbW1@^9h0LbMbK4TT1VafF$&p`uDTj4yn8VBmRLmEC!$!M53i7fL;ry%LEr z%Wrg!RZNp+nYn9+=4AJ4r+eFR3v7(mhOyiC7QL@Clm5r)RCp%FYx{ril4rZ!HWk|uAOVtEUR zbZ zPG+uxzX`mp9yzeu1TgBk*g2e1;GhQCdDrvcB+evF(1b3bvS)I#b`ck<5Hm)sUv^|DHtTd?P3MB^&GMP=&2pV`^W<&sb>it* zI_tt62FxS8=U^%fjOZfUNIHiLeDw!p5%`+S=i7%$MP3bF6;39_jZK}$-93zzkR+j# zsf*#*oOoP0?O-+VLu4MAfrbMD%k>kyx{9iUa@^_IOO9ip@c_@651)c6m=Zwq-80!d z8!DhfbWByad)K^tr&bL6tN8bI-+F7PX3LJi8~+|u-S{W{vPLSRiQ zsYuB|I_)+&=I&gd2SV_-Ks)uo6(ZTp1?*PjACe^K(fBf`BnGi$WxA1>WTv*#G%l{4 zx4$7YxcRbUD2iFG{R-A(&xe2bWNd(%>m1Jum{3#@_n_oPovMA@(%qE?PHtuOOyNU9 z1VF(4bN(E$wC!;oqRaDYnPX&w-c_%*8V+5hs=gUp4HC`{b_32z9_@n0x2_?bIcL`c z{x9`BQb2MglRbksX>q^1Ggsj{;Uh7z<;6}PV(2ZX^kz&fe52thE++4#{8H|IGUzep zyk154+tM_sbD!3C*W=U_G#9e@)u5_$L-ENS4%r<|L(HHf%c7dk` zc8?=qU*iiJ5eh@sG)IGQeKaXf7DVQuN7@@rm^{`)B)`7+Uup^(ZZJjSmcstV^b3E? z(*L4#X9+m(0OZn2blw&WmqQ7(@0akAK$nE5i%R?rIr34}0+(S@ED{=4HU-r^JJ!j- z+=vzg)3c-c%?;q&d&O|Q2GcPw9Znoqy9zr~4R92PHFLeZ=o{12 znd9C1v)C2ZYm4{G>RXXm*+cu~SQp%e{-9 zEGCO?Cnwee@qoxubv{=2@jNaJYOoG=i||$`>D@?cWZJjTEpVD-`vWSY4^d9Qja@T= z36q+%CJ(7qki!z1YCvQ^)$z_=V0Iq;vm1opTON0b(GWq`Vb}mK-=rM-x*PLkHVN91 z3L0$|Lb0=3wLyOMGOAeSMAyYI=@N=w(jJ#)oPZYOPm&KD*AN#ZnzL-cUXBgF}9y zJFep9e5R(KhwDdrNE8n-p25d9lRNzq7v|Y>c8^6ZDH=oU?cZ1GrsGS+JtMFQ)1Mv* z)*G!=k&F&pRqys?1JJgY+f*>fzdB!jY5RUjr8{BeRR zozH)6R&>sVP&t#hzilbi*Z z(c?0vRbK|DEu^`7+fQbdai67EW*)KV#}kV$xXFsUSIqqCk(r-?WL7}{d(q0xF++Nv z9QSXRrx?UpbGM>BoAI@s2LZ9-`$qUW8m?x<$X7+N4`vH0>pQJeIQx!FKdY4;&}BYW zw$$cj!Ppwjmo6SOZiMAh977?Rzm^w@N7o@XvdP)zJPr?SGv*S@sgxjr5TIQp?-xk5Y{%AOZOY$OF+vmWw*@%S~%}phHCAh#;pH zR&l%J^xe9<@bpXQ|oba#% zYSQ$JBD_#-GzwwCmwB>N6jG)^AsUkoUH9(s;}wchgSvdOHfo=(@ghUeE%ibM(pOnS zcqjFFC{CY!XC4cTT|KbALrIX5P363$)$O)=_NQ4nN5%J^;flxujD}AUfM3E3)1+dG zpP1pvxBe+%oFiHmj|tdVd^x2N8@}{!* z4E%4-_xtlK)?&u-KurSd@Xd$-hwsKIRW*#8?qGhlX!BqfS;e9%-;`&ZyMta`F{nBp ztBGfpef0#UTalI_h+)$TjdJ;Yt~heA5j=$BKxXM!#n<~&Cp#>xq2~;$OMv9(PYmKa zR(9s$%X1c}d(xiSaD-nng@c=CO{N=C-r@|+Mx9+5ifRmsPDmJQ3j=-^e^xHciA#me zG?WwC2g}4l^e;K z;mU7rs4L96 z{W$rl6X|AE;XO5sv3`cXC#QFk$)lr|!`b{=gH`nH?tPt7Kg7)PP}?19x?K_!mh5_R zK!F9S`O0z!JS7jh)ydKf+0lHTmRwnQY8;*| zJ&ue_tumhROfWgd`oXKkH(s?==%$x*>CU1aNL)i%xr=B0%*yUpFq_I&WLGSR4OwKV zNrv)f zb5KDh;kFg|39NZnRwu@eU7yVr!paI|k4#V|_ZbD}o{+^-LR1p!kzCa+@j*I55jXba z?7%_1KnKt`Z;u?}m+!4k$dlE(qgwofHqmX+4fCLEQ7ORj2@gU(*2-k&&QXeUY@Rx! zy;to%163MBQ!K6>N*C8#;bn2ewxT+wC};IY@SfhXX52c#$w~dDe4<~`wvbaLA4{yS z?{k6e*k@Q|#2)~HQ86g9VeK`gsA5hyL=NU3F${pz$E(-1ID6ok^>u@>BIM($(RzN> zX=e)spb;-2ex)buef*@*X4pgSZ2)x7ipVxyA|Qn;--2oXtEe&quBjzU+jc-Qcj2kh z`hqS4n6bMVnhKoO7m#tEx{ZRrtCk2eBWk><1O_6_`JVHVr0yF$u>|m?PG7H{*Ttv5MJUCI{Cs^^M4mMr(fhUFYkW}^fNCY zD`o$+Vz#1eN;mbqNOP!@%@FJ2BZEqW-r`|gw8$}qh8Tt8m3_ca%DZ^wcJl(eCiyru zhpaOp=H`~cL$kU{ZHNBf5hd4dwV-*z|ARt;Nk(xK@qTG4-Q-Sa~2iI@57Bzh8}wc$4w zdZMbklcSZ9O3^j#xUSJGVt3F!v=e=5953fZuT{}_Quq?+cIJ{U!f`T1PZhl8io&)l zM&=0%DynGl|V8-FpMFK6o4=drTCI{G9_czodC$1dt*kZVq3fL*E?G z_NGpbe}dpI4UE9EDiSf4V+v$H3PIN^`rz7$BVQSBT+)`GF&MA)z0Q>;I;_^Fh2Q_l zksJLaAOy(^>b5l}l0^$6IF1lZ0sD`WXmSCl?HPytfBvTh7&DrRQv=#YsaCwdN#G6R z%kW^wEX4%=;ekLG`AEfQ2+K~jAb=U^=?Q0pjq1^#1OM<(0!?)2spYUJl$)gMNp0N` z_xGZW10-QYHy@=E!yUKE;w#~|}TmN+?Z}gihv1@*+#p}4|5;5@W zM~RbmIH_y`cT0B5h`k{JgSpYs^C`jbL~?PnFihLEf5KP#ZG(Lz1iB5C^|VGOEv`cO zA{Wj)pMzsuCsyeJ^Z3R*v`?hnLVL_32{ZgS=UHm#dh@Cxs^4gxsro+R1^tQA!(kU> z7uCTjo+6c2b~xh&@E**Rfj+}I%Y18L0CjvwQVps+Kz^2tP&FYL@XnX2_9HR4z^wUc z=$l$bj2>*FSVjJY#bOTMXs$7>61^Gw`uvOL_V?!RVH`ZXT0sf}XtuC&YH(F>^wb+M zV~}QCFI(pV0@(|EncwG%)NaSra~zf)@COuvt(L`M>1tP@+yb=Auqo#7s7V)rz22;96ng_zmcXJHf*M{NmH?< zXlR-=+CUZ=@}(Y4bB;!SY#e`^MhW6(u4raDq_Zakr7g>eTaxXc zLhNDKGx}8s#pjly;N7YrEwCkymR9xt$*qbAZ@li46hgO5gv0_fE=SPU!00?y71ysepHR(pMYvSuO`vu@Zalk;Tr+l# z>|58pTACAqJDh-#*g1CBxdWQ~YF|MRCE?fg#WkK1M<$%*%jk9tSQlc=%y#62btfeF zh?=LMzlc&atC^M{rS{_4>U%xE+NLW?Yme@xZ&Zitui1--691=WPtg6Jnq9akc250n z-eVqmr}SU-2K|4mo&k;#yxgq3Iz26%a*Vxd`|B3C!la@NYh^a9it!&FKR7xoN=z1` zHilq|vTW+C!%Ew?Mvx>2^vE{y={_RKR|}1DC7X$!+ec z2qBBuw8Zw=F$afyMfcx{j( z{G6r>K~Bhn2jEl8RQsk&Lu2N(SD?8RA(vc*mDHN=Vd`u*tLuY7pE*guDCcCJa%QEq zv)V@SMOwO3D|tb!>B&OT0;y8G&~Wor{aR{S!ffi1YQzB(WXu|-Xixx)brAohF|yGh zPA{uGlq8m?5GFj&U{*3>5f=X&Pu8E8505WrHhjjRumy}}5&;r1lzM>{LJQ-2>xo8i z&jDQ$CpY;Wna60)fH#=<(dPa$$7D1Qzpb0Q=a=}acj3?NetIGJWL5`?mHI)HniD_VjhlztIAgh$P3LXRcfMxm>^h*uIh$-@~_XuI? z10BXcyij^QiVQcGr<3*cWe*zEXLwq9d6OBxFutOTi%u=b$m7p2cEbROEei5s8rGr;Z??X`6gichXsg338 zgUAfg$M)*AUFy(8eD9ae>y=kuD}84B_0s8wcsNpc1_JReZ@!KWb6?cpE(ZFKPj`xI zUv8^w#^`CCPe^7V#JyfHv4E&7y(%v!5QNTMaF!BKuMUFtg zZiY$)698bR$5uS2t&}rJ@K6%cz-1USC`V=B)|mB@{od6Ql5VEo!+;NLPVJLxit7A1 zF4FR4CiVVzT+XiGrFz4SMAor09VtAh%!Rett*7@xUB$w`UY0iaz{=5I)=#fo9m2-m)l|PAR|_s%y5!~EY*OoC;h6R7D~5BX6gguoj?gIE zMCof|T3<;7)`S3L^PN`Ahpy|R3^>9ksSk=MdJ0)yF=naGJLmk|e>>ehhKKZGA z7;io}Yz2tK4H*I(%vL+YlXKwgKQNbdzvaI3XcK=tDNG z)Eh(wzJP5U*ofwIium7?GLnq$XcB!~BX8k#GtgV1IV!9@%nb0OVHHKq|{u_S_T&qDzIS zk&v^Dak{yTdW2V76Ck04`v;`&6$CcP_fjjQ!AY}Z{v#T2YmNLC4zO`bXpLv8n5HDw zOf-EV0@iI+>Kv}HkR@IJ0^GHkC-RvOf#dYi6e7ad2{17a%Sn>2 zGi0mJdYQvq6_cFJ5S3Lju82MBXn8ZzLQ*c63MN~9*|sS01i|mqEJSWZ!B7_@E6a(z z;%keMzZ@J2rw!3DafgPt!+VYnU~$Qc-|c_t-^R@2yj``E=XXUGx=D)l24%LK7hU=V zUYM73Sx+M_VCTdd{SK(5(Fx`~O$@B8w9uD*_N>NQEXTjNof&_G%%pgXRYV3Jsmq3S zJ+{5!euS~Bgq7rXu#d=1{ulp{uqD4 zHE#xl77el4lmxa?dGF$wCKs$pihf?KG5CwNWCHimcFC}Gwuk>_H0}KYDg8ch!><2(d?vP zN~=qE$C0?>-cK4)bIo3-y~TVnqx1ZE+ckYeoFM~z!?;`D$L?XW6Lu!qL?pJVv{oI6 z$u{4jhUVk`UGZW@yk1B8OgeEM@&2Ig2l{{;4F3l$mKf|^m;%Wo7~jPmr%YOD;wG(q z{jDzgF99`G2g_XnH#0_V8|FxcZX4fL0`JzcxujdeqrBn@MKfGRgOQ}>_t0@x%Bo%= zF|!HzR<1ngd0B0r9`A`)9bBOWq!(IA0?1oBXuAhZUW>3>Z>nUd>59oQYZq;#=@4qL zbA{YVXqnL4Ddk6r72&I!ad!&SM+VkHBkX=C>(`NB14~|&y{sSyD>I}ZXvdgCbk7FP zO2eJs&dOKtWH)UYJMQ8YiF@I>cEW-_IWh z1Ocwzl+U5WSU2oVxS#bG$VpPKK_``Hi@tW#6Czko>G7PtR2|6&f7wzz(K-P=WldevIp4Mza=e2O}5A);h zqOM51kh-wCk1HV+=MWLcf4-(}b1*b}g0+n`1U;*h)(r;uIx*nqK`Ukd6Hml*AF}A0 zMe|8#gtD?`Vpbzk=fBo}bDvL`ckT0$jNL5l zYrc?P`I$v2nF)%($Sx1|6m`!H6lOP=o{COWx>xcnTe3)z#;b1C=JDQg*9i{ox*KB= zs!j~JrE$49Cu&p^;AeH%wX6rWh19LT<=TV@-J_H~5*~u#vwwM2YD|4jIKNS3yh?Z!B z>wg>@=g8UbLziGg_O=fUohT-o5nxkjLqC=>hmSJAsu(Y(St$BW8eM}MNY&KrsixWx zcbYyjELDMYcQi5(pu9l400B5c-R$|3E$&@mr~}^8KvcrcV{y~1mmwEk|vz*}o4la`aLsf5M3fKM_JxFCAO=M|u^IxPPT*F4*>1+Vuf*I#BE8 z?(4!%0@SEYgPS=lwm2B*ZcM&tqN&nCu4B#zE)piFCz~$qCg^v;0umTu` zKUljU=VKQdGpjea2|ER}oj$snTnjJD5d7`LuH=Uz{}O)ef*tzi{WtI(v&tzp=mK<9 zvKj5XDm~(ygBq$T%_z*WA-<|cziQ$?afz6Q57-+05dTUClb znnvaDYAcs^r1NM(4du##GOaC%d4ilwTIIYJ+9sjW>c1k>5X$Oh&QDu4WSu#`J8OKM zkU1bC!#-fYulNpLAy;k&}OfmJ@e zZAba#kd_Co*ST2I44GzbdJ}y+0SWvqKaQ`G5kAE} zJ4YK9sk3p-!jz_PaLOG_!bp^eLi0JnNl&CfblR0r5zdS)C1m=j&42Y4vv=&{HnzML zSc;}M1|>jb7Imp5HGpy<*|<3l+lDOPds71zNoG-Xt1yk93yXEy05)2Dp&c&gKn=%_ zQ;O+A(9bqFW(PLY^viKp+tSLdOyXp z)UJ03tSq}F<2BdgtcNb)<{Zzvxs$pfv5kmD;yg&z-W<5Uu;K=^WwBj3dXCks28_Ub zizq#^vO~UQ80r-GTe}HvdqNyQIN=|)k--%y{xFUw!_gQ2;akC3_u(5sLSLw#xzobK z#6FnkDP|M=SqThzjJX`kNU9WcdPWQ6@)%0jE+*5JUXX7)f9(8Y5hpF&LdB)XS)JB_ zI8}4O50X+chi-T)IZi{sQq}>cPyKsa9^^9OhCxXt z_*Qp6>-6<3r8*1DReE@K!%9PGR@e<^%d99UPOx8{<4~%=km=3^jCgMV7m1rg`t@N5 zdtg@RSp%7+tVlC@$9&}ibNOmppaAS1Dq-Z%KsRp~zVMMt#PD?kN(n2D7Hm;ZzLQ{= zFUdSIT!(3Sb>VvXTJ)Bn&K?%ia%HN>w<^q&BU50sw$vh^SB+y!#^%U-AnO=fK@NWJ z8niWa-CY9Tes=nF()ElMP)EV`_#dj}9|O+F7Y4d?e0dG|_o()!z##$PZ{OpFbs|W% z28t{8GyXPOE{OL1arYwm3#*c;2gs`V1nRE&r1qt3+_s#PD~DNt0|H^{7TF%x{6d-^ zxBi9lsXM=HGX{@viWXYuw^$|jx+R7n^98%??Jqx*Knlt)_OAnICEZ_w!ZET|QUBbL z9oI$*U}0+}>Q1_;QQ$0B^J<%ZtQdktNWAT<>}ftjrrG(N$^=V3D*&@siA9 z=^*_#Y#1#-HLZ4mvDl2?Q`g^DYj&*pw9KNLQy+&g$92<=?hoCnZlb9l-9hkVzrK}d z3h>!_suQ@dx|&}MI*rm|^dE7tP71`@M1O|PBcj~39^uhMCYp-uGRxVFDg_e)KgXVJ zZnSm~!ekP8{s&`!1LLdVT;JGW1mn4euR^3s_~@m0-(@e&uaPh@2Q<{vD_3w22d0)S9@hOS?2jllsj zV8gx@v6>Y}s^?W*nob{t!Q>j1-#SPo=IC==ZT`kT{a{kp!RvZ0NlE@e9P$|oLV0GeV@L(fx>xPSy9`u?RO8~LQQU3)3pqg1=gN6XzFi8Z=m^|A*^P^UbZ8e>-^5fCXoE|#M;U{%%eEp z@$+tJa%1MGK!uj;DA(q$QzdRN5yFZOz7D_z8ATx3ZKlFYL8{xg<8N$+|I5AuaBr%8 z;U{_%9J(dtrlH|r6msT+J&#uXqAvW;iN3A| z1xCJC%qn`zcxflQ^`A6>hC(xe^1bji8ljGT9V#3MQ_-l?g@<+gb^{@C!J~l|E(%6V z@Wte&OdT_{Nex_fV{Ep#2l#n>!6;rVmsp6wW80Tp7;&!nW;^USDqnXPV;N z5+DpZmGxb-?Yb4%;;75L{u>H1UAqQI1VK^K7CaZ$9ht(i;8vMsRiSQE)))75OT=(^ zzxnC$3O;fls@oa1RbqFwJHRYCX{2nVAS^`LUewA2dQFhQ^^fuzjLF*Dy(}r;c6I0J zr-x53{?1hrrGC98o&TY*d*mI0Zrtw~%o!SsmNsTV!X5GsO~+ga z)1@R5l#8{n881vm*a*>t$5cKE(+R?+@LLrIc!mB-JcdZ_*D(>T>i?Va#!C-~S6jee z)Tl0tE*xa!38oy`v0?RRpI%`nXiil%U2I3hX(LuO0OTl0wjmO5B(p{3B2>DJqhOad zvxWTJ)heVAS>x$#*@Y9nVLv!UfiI_|_@ovparUT}q1B($dHr8DltOX8FXZ?(9=tb_ zgv#Vw$uglj@pUo-bE_^M(^ z(|&F7m+V0MMEGDsYs{cK zpvSn%yc_D?>?tHZ*LxDl#7~rRzfF8j`V}o2%fW0rvT4r|Ufm>O*td%Dpy;t=U@=p z-HkYNbwH+y$BLG3P;+I<+jN7l!66{B1M7HY$JT|oWap9iU)v?i1u#0vd`=ltW}zqK zgFwChEp3#wPS}(o3CIgsQX8@!-|y3|w;~t@0(eX76Dr)1jay&I@R}Q6CAk;SNK4Ho zH$UoD5^v{>3|Ggxi#9%oJ6l5Y)8RU7qV6uXO)@n*Hx;<~_IkUxIm+c}(WgC2?_F?sz_> zq1r!3sr@c6I>&ufDp?xgs;`%{CF6ONt6WNxI_V)SO<1=m;>Ta-?@&s|L)JTw9xfUK zs%koNN&S@mDk*fOX$KhdV44KRFoy9x;vHW(Jg_Qrlr)tt+Yp7ZG+_uHX~<|EwhT|k(DMMPCP%DJrH&x z&JgpQPIBx~|8ilU-MEGkGu-~Q_X%7o?kd}xMv|@_VIZ)<9-(liLg;@wrIda@jOT1; zL)US;1<*#i`D2t?uzoAGxc=5R-o=!ZM5me7p~hDe>`~T%J+Z7?6$?<1@fO%VugIKr z+^>tDTf9y8rAqf6P{P-c4U(eBQuP8SyF>(1ZcWkOQS$S`vwb5{wdY;SIvrU|5S!&* z93c4Z8S;~I<|Gxb%q1q0Rctfz$n`pnrLh;7El|()IiDuV33bo=taBjVx!F#D0yUNn#>5}F+WUP zQ$ld^J1SaG1sK+nU?T&is;j;4BMM|iQ^C+e(?Rwyvtp(BFoxTH4}sN>bUn)=pT!`@ zq`)GZNDdR>r)lMr!(Ww48bBPhAe94t8v-`-NKg!zM%{jVf}S&}e~L{Hk4-}i*jbOQ zhULkN=IMrXo`nWqKd0VmMbBGntCRg@yPaaRk&&}&!g&ZSv5--G#f5AC|8d_+s9W&} z4uw)!_C^O3J@Nf>X*<0Nxj2e?n2XS!U+7hN0P+mS&p4;U5_hGyeCq#c0iTLkCdQ@9 z(JTr;Vp{Iy zlP(UH$s-;Zxx-tm$R88N26D-;KKrra(~F;T%d@-iCMtG zhUIPCc-E48O*fcU2!0J7mEA9*@DYu^N=*J3{=sVUCYPGc==x|5wzxWS`0BO>sIj@b z=agU(gF$8QHcjsw$t`T1%!Pqi?QQz_C&`Ru^J=se`#)WQVnj5KD9J6m;NpSMxiIF5SK3W2aPd3;ixJU1b1GRZgx6C&bwLIw#R(=-s#ibN)U6dC8{089I(z zvTHR=ijqnoRmaF^V$Z>+roi&MOhXUC7%e8v5u)L`LE0>9i0sMYo5cG`OJt@dNr(tP zDlCr4X!%-?SrDI}*6cN+xq{g>~pWs6c&J-+1+yDpUm%DrmPgair5WLZKqf4l@49L z7zDb%d-|;!gwFzMXn#noo-#YohCT-7ta!^+)+Km(Slerx>mVsVVth2^(~Ru}Y*6;f z5}I|;4BN$pQjqG*8NE^g9G;foW%@n8BJ6IfG)nqa)&1CrUHB|~GbB0x8++Q#6-|iy zB~&!?rjC-tUWcbl30twf=7*@AVGqGrk_G44O>mk%ktMHj0~KVdy;|7wJ4_upYhpgS zN=2!_fNtU%`i5E&QGjyQuE|ukCPv~ibZ7kW=dmEy-mvPZ)}9>K9ijpu+P54^wz>ZC z3XKdA+*xZfv+J1VHYy{L*2IU4wK*9TgKDX1TA+jS=mZa*hheKrXMA6`h3S$bf z*<#>;6ZsL!*U6PM$*Kq^0r4%cZ9m<&=>n>r#`yN8p=_R0WG9xdaa~u_jirlMX=ff&t|I$>zAtco<9BEe zyXR|sPQO)rn&>Mg_CaDwe&+@(NqYoS;v+TspBN-0HJT!XZ@2X`s1#ob+ky96j&+@0VS zJXnB`m;Zh4ecn&|eRg(s_sltGvJwN;y@@VqiKBEZ=9Z$V{d9O2bu2+8MrO2A@?SIQ z#>Tv)t8Nfd@2vD`Mxz!;5Fk^*2j@O? z(od=8eEMbC5@WPe?8>=gbTsVVxhco?S*#Q~8Q+>c51yk9vbnSU!RbrUiw=7t`O)HN zUp|nuEv^2s1oA1v63Zc5*ypHPQkHjl|$tgXe4l1GvT!&*`D3Q9eea|*H&u8 zaKzv=03`Dwfq3mdr3(97bRRmlLOw(?MqCKFu*r5c$>xg9Vlg0=$YdGP5sAQRy+!0e zUhWhR*GPsA-iN_Z6Pdk?GEa<6VTGYup&6l0d`cfP617r|#a_8t#lUapUR~3i-0dM1 zyka%=pJYBmbLh;t25jEr`)bJ8=Jb%2U*3uiwZ(7`h_mb%^bXc9)_v!b*Y<)Maluet zGr8?L#z8nOxHLb%`eY_+R9w9jTMQ!gZ0XNDEv&u=LLOrJ|8m@Z*vP{zVB#pZ)qO$jDfMhW>K6;w5exqr zw@IdgfQG~%3&WFU#eHYdh8qV$VsFhStA)# z4h;M~StLL{XWq}~#4W9NU??P8)pxy=!P;YH5nNzp=)mR4&Oh28WOjdl-J7H8=^AE_J>E29npxL@vX zu8rf3uxuewVI^$XDD+i3MkIk8TUx)(3+Gek4M@v2CWb`XYp=09&%NPIKL=CME4O_1 z^VRnh=Elduf{cy91g7lmDQj)R#|1qub_0!l=i7D!LgHTJi!*PpR@|6GzC5zJdj>2h z`jZTg+Hd|x=CU!<+5BfwMcmY|b(_5w(Sg&i`XXI<_3xw7IFvUBqjpN|dTiz5)De=5 z#2Ka?W~QG34bcvjg11uJ6N#BOrVPd)m%&mMUR3a8e~80rlh5Da)5TJ-lM$HbDa_or zYZ#lVdk32Vdh=MIzpYvWob%}R5O*4OG&&`4LXVu9UeSMfRm>Y%d2%-msSV41i1y76 zlf|RrxHR}^7i-wt|LJmyhNOpq2x~Kfk&uS0nmnVu6h$dcnJ{SoMnNr|40~B}l4E(EI_+0~Bx6xUp}1M@7oe1)G%sQ?YjTDv zVTwnWT7ckucw z#vu-@4r- z4J5}X=Xo0A9Ugs#`&xy}HOdQ=&u%~5zF!s6l5oo>*ZE#%Kv3{IAF9aE z^VvBiJY*n@gF-I3m2%;PbU}1^C4g+UjhHTTbcD;CEA_=t?v4&^wPyUqgkGdZRJY(` zg|0Ctc6fpts3EfNO~9|SfRNNf&bMox3;i3@*Gx_U&H{9o`wosyatw)igRfebLuoc% zCsO^`#*6*_=eSmfCI9!7Gkw11jFayLHs zV4=Hub=H04B6=O=4j9M0*flt{eBGefV? znkJ`we;nps9ra~B)j|@Hhs#om(q5*`2Mm&Kqlx94lUBPPGU;a{-wEy_($GuZi=pjq zx=0YL?eU7^udewuMlI$)Ho@o6K~`})W>X2(>@0BKV@BcW$wazK^mL&3->E(~j<)Tl z`n_awe+SAr`0~wm%wpJ!=ymev)3MMk^keSxpas%I8vKa77V`U>Nbd=A^(B3x5s?hP zZ}*KUdGsjR0@~nv7F?(EhY<;3bdzv0M_5e$>HZVyc3FFxS?M_%>#9*A5E=ne zql#Iqn&+X)Nt=-b{%gqjaFG+Jkv7}ZTLZWGyDM~8RkKCkFBqDk;s+U?zV1y^?I^_( zNq^Y3@01NESDAY;#kKm>8p?F}cUQ6V+a$r!=eC89b7k(9PbwRj9xradK=5h6^RHY) ziA7hr=f@7@8M3nond5&QM+ehw6hgw*k-7orXq|T(LJW7h*Fs&FwYyB6aKFWmQpSGg zAHhave-%=Efv~Y-1EO@iFb+MiT?{iVaeG{)GMA6ay?M+?y5XCsa~af>JEFF%(!3IH zjh3?_?iBdv_wIz9eaCnNnRSnRQE4H@pBVNl>bBbqjuf$bZ5hwE&D={j`zzLM?v6-~h7rV1nWuNVRS`x84H9?Q^UinN)_Cr^kSEM=9%JigL zg^#ZHU9VG-vr_xADXidDK-%zwZIRi$nl$fW(1N_spm{LsJ;8qqY583JQExv_;^KUy z&ECes`chwzx&D3(#W*662A3BtHM8qQrecJGZu3veR=Da5eiD?1bK!bGb{6}ci7i2V z9pB-ENjK*EDqLI94ZlCT+I)->J7Z(_n4a}I%&{hKM2XDqGSYy;l=iY`9al;L&Wk>j zn{D>ifR}(CU_Wo>cIuChUyJ>_%Q-69UxQqy&}LM6zibP*W9$5R1aitR`R4qRyJwX_ zM^gIfJ<9nd$#3Fs4xFdxQN*4OQNB%l2YxV%C0DBnVkGf@Do2PmtOvmW2;iTn^-wZJU2zb?w zRu@?fOUr#9%{j6i$A|e^UbQ8eezY16BLTyi#ZjKt0B>8iSG?@4Kfj3Gsid*(#0PcK zr@k~Xtwq_ae{puucHLeh%+WQc7*JG^ov zoF)=-(3B)YU?xBm9*Rb$`G|(oHqgrUDM;3U8=E;GZy!JmtA-+dPH zzy*1d_kTMLc@*>W?_S7t@Fqia`#)K9A8PrG3W1UGiwOBd@Yv?!3(40LiMW&ew2J+W z@oJ9o>%)7D?kM+W$&;5o;awjB%rF{3VS8CZDuJgaf71ml$SjBsG~*m4X6^6s;uUpc zg$MJ2!Jy5^<|Jmhq0DIX>1i**-XnL@c^`|Ypsm&rfoZ2<(E&cPdbW70pnqQ{TPihj z$5G|}3Cm{7N;@~@-iJ%IJ^}sH=R&R(V@tTr0F)N3E5mssyy))=48F|Rkc?KJUKl84 z@JENl%rDl<_WqZ=J8xR6ZQ}Y}A_Qap4?Q=3=4vM9(&gvJXZ`!VywIrQZjXFCq~zbD z(2nrAi?#3&E47fNkkH;MUFb2K6IjQ>5?B;+%u{8gW-DJN8f+V=v6%b*Y9K0{bV=Ku z=T#`Gb0n3~?#KTa!;RX*zhiKBU8aW!uZt%`L3;GWX0}o6RD~N9%V`vHm;0E7zB_EG z$x9q27uhK_H-Sg)7Jz?J;}0i~xg$bn{(86b8^#XLxsNH6eu_fV=Z_LniFe@7V1vO- zu+TKmZSC$x>oeeROMYXBrCa@q3w(kA)Mi1SZ~PDa(`)AC0vI_YhR{!WT1gl~rWnyZ zHayzd*{E%Em0CVl3jYzd5g8JPU@b~5OmpT05*UtE#lGIrBooWYaTHQ2n%qy06%Gv@ zwJZ&QQw9*P0rR7(Ud-lbW|mgI{%XZUCBge^V=HQ`x0V=pwJxPwr(zqTNd>f5QS-;tek`yw>n!mSM6u`DFb?r=$ zyydU9di7oc#S18R(}q(LaT>8|&IYAst~{qNl&_q$c&gChzZ*~5fmPSr6kflPx-3TS zBH!^o7lR#(#j+O(GjbM>?$(9ZQKlr=9^SQ^!#fBs@!oYGk&eH8~LmDCp3b5W6Xj{Hm-WnISWlh@Ye`x zYx~?W<;VXjSk_zBf;3fuc%SuTId>PjHg1R2?^c=(C5B=k25T!#*LzBoJIwFDTGqvy z5@PJ4+{y(R7}r}6IGHhaJcDy4 zpCpQ;jw#?OJ&&EV7xVW*=YDQy<71gC3c8Ep7*8W{*SxUr$B#rK4o`oPVLT6fBdf>o zSDQCJO9xjDqj2^mZ=Zc6+ySwF|3X!{@?q<7=kKN=R+iN96Jj*;WwL*^KQ2AUPL?zi zk9@HIJ=FF$A|;O&tLDSAqd8w_3C|F){G!9`wG*GO-QLpGtbk0HiT4@xe*yHfZA!qH zm}SrECSwmRcY8Y*$8090Q(fEf+r1Qartpl3n}Adi{M|yoTh*`bl4!=7Co}(&6j~Ja ze6w|w?IhkkB~Kap?xdHTCeZTmEr|4k-d~~StEjsN9MB}tI9U~lM&44aVK#Jim3`MB z(?HcRp?D|!V^hz*(d)kwMIqHFE1lMqR1E9@qUN@;70NHK3yktl$q$U@tf*BA1WP2H z>?}qMp-Tu%%kvv;*!zX)521MYvid__gE_{J^5dZVA0Jk&ym{Sg3+6l}R2=^h*)zo( zXrOoo=p31+8P0%gZD9i&zb;>TQ)>PqLdPwJEny9iOYe`5C)yXeue$Dz9L5f$?#AJ* z_O=^6lB041Eq)OWkKoglejm$+e5qSX$>uOt#-#4^yXSAO?N zVUWQ)nUSss(_A>1>zn}^79e%awiB}g?TqtnYnJ+ZMeCvVpdxvPbhZ&U*l6+3S51YU zyaaRV7=|_8o9wth{DSYRks_AdJ{-QHI5#j0w_uA@D`#&JFbYI7R<6-{{e98HPEeIo zhunsL&~0Cx5kP2FX`OAD^4IlABBS)$Md}8!bf}(ysmRoY8bZP&Q?>zn#&V;!{+B{XJ&?haFQrAL?Q%cIj- z*1~ru`HPG^XD(Tvs5DX!Ye3I}A3U(l7*PT>)4`oLe2fe}TwGwUsG{N-yd8DIzlm;Y z@yar(K|~UM4Y6K6E6z~h3X%X&FAG%245|aTC?~XZM!LGx;SV)S?^#Vqblht;dcFN# zAPMlx7tDc-*qYeN!B!H-M?{DT*m;SZVtj;MvX+a&S!UrtAcPyx@KOiyN^)E?6A zs-8RS44V~AGxDn;$dd#C*p*~SqRaddds#X(^DhJf+ z_pt^Q@T(u1B-$|Tc<{X3N@gn~p@*aY5;52_SZJU4wHJFP%xV1|qN9Z@c*BS>F@8$h zy#Y;pqX*n)x`KZ|5OCD)zc;-jzK^ktPt&bz4waApuMxp_ zCYSJ7-0FU|vw9D}-4E_*xoqxoSbzK;`FLrvcrKUn$T5jFwsSjgTdWlK<1&-HJhZ*tC=>K#pz-U>%l-QFvM9b*o63fE5keKm2g-90rXMd|YrcLl|Df*7Wt_c=NNl4B2fDC5 zcrhH%!D{aATfCDTYt7kN$5YUTV|>s^9^e9W{VHb5CL{!io@npJ&(0$swpGvN7UMtc_ zB!PFZ{fi*&h#3Ff+{w6Spg$)=pVajbQuejoKpJ)F|zGXimXZD zv;od$|Lk<+UadjmfX~F0dyAvuIEazwcF{-Jz8_qSvs;f?k+HeiqW2t}E{we`Vxyzx ziAO$omZbtbJUajQO`W5)I_l37#{qnJOF0MC^comFkI-Fw6EUd&KD%;UcLQjKJ}6$` zQIHs%I3N^5@J%R9iVA>57n%Rq|9h|bc^Z=P9Ou6R5C03kJz!UNf=8vR-quBkM+gwL zy=jignP|sw4adGq;-pK3_&6d;WGrpz#0i^eo;fj8t(z7WkCo?9ez6^`=3khi*JNIX z7IT2Ctg9?}WH8N6%Q=OOxhdp%eq)|ewr79*79MR!XCU$Gg{@WWJiLmjs^4qB`&?FV{)7)anaOprkU77p8srLi=GO zJu#EGhOdc~)MHs_}k~qepH}K4C~t)J2jAUa1+^oubINXwG2u|8Cn4RcW-W&tOlkU zW3hYs_vt1UU*jmrc3r1srM^H`97p1CpH1&*!9!mnnHmFIm^llyjQ*w@cD>^2iC3Nd zX;G1ULDMrihuFEd!&PUHxU6LVg@@NPDV0ca&g(A{DUP6!v2IbGNJSK_U>b$~FP*Oy zf=WcyuAt;OVeH;0-T3|5X zmKX4QM)^c|Gv<^d5Wl%t-{MSJx!n3k-R(|rkNK0Ye^ow@JNpJI`}<`FfrL* zCaGF36;01cMFh>`lu`wsryZ&mAe&qS-L(qt^ontJOiYiZDVPA>_L4sAmtlwD*WpAq zZR!gy9E&X3*s{mdQpM;d;G`XRaY`Cc38LCn|NnGkGwgeuJU9B-Y&eU}s>9yf-RWSD zP)}~p4NuZ!3(Z8TaHSY|N2Q}JbC;)9h0HMe#_cxU5IJ`uxozKOL5j6S+(LViF#Nwf z{oD(q0gekafjc%9#mUH3M(=o@7R0ht@=XiU%RGnUN7?P7E9M&)pFaa#W4`ZjFI<8? z9Jcca*%k}7%5Iz8-hTp@Xt?5>RsPnCHj%W?!$P^h5oIdP(NiS0qG6@~F?dd|+!Cu^ zI7OQ-2glO}hxU6cmOPO6UIf-2H?f>U=y(8M^_U5)7iy+~lo7a4DdNIu36_)A#HYv;3 zS2F|S$oG_p;xK|b8Zz^xJqxeA3Xh%!vmy}vs4G^@p;KuUKk&tW0spVKRI7AU7srRU z&qKr@sNz@;);BI}9}8C%xacJo3p?727 z-pz1kvK=a*C;J2pWx1qgHt@W4M^_jSzat?P4Egj5_o;OqXGn`nEJQe^I^HJG4Z?dRnd;^*mj(SZZXH;>xq9=F3hB6eUZjC+k=hd zY{{j=PN6+kv=@$|VF3^yfl^!ocZ1HOoI+%>zx7GY&s}X9R>eDQr0m zey|<5rY86h_TN12yKUhD9j+7)OXn{oJ5w!A$0@juQEDb;td4WzCe^J+q0_^bWZChsOv^Lu{9_YQO|Bv{&vl2MzpFf$Q4w_6C0SWHvYWV8hcrF|yy{!fEMx+O) zn8ie*h}V*;(NtpSGrS#7nd(>bfxNVhEUlP74Z9HN;{0-CCHNDIzckBFKpkC-4XET3 z_B%i(ciuQuBgb>UJl{f$vCEVVy(T_^>t7-X0N5rqZYctA*J z=@<1GbWJXP%{>0;K_?$oYRo}l1cvetX??!?|76=R{6zAyYwNPU7t%2exRz%A6!vS0 ziyQi4(On*B7gUj0GT7fpR`&7mN1ku1ebB4k4XHd{GN135sf6)Te7+$}gu~zaJxbqf ze({$nsGk3K@p}fk!VyKYAV{~}Cw%F(2zow%HYk-sWA=ZS!8AR9*FxY2yTy?f@SI zggRs{>FDDgu3UQJmUT6${Xdz}Se#7Ixr_z9bm|#Y0#$3&T5Z|}dntt0n!jD`pYtHB zHaV%D$E5zwjSae_*c~|=m^Dp1H8<1mpp&`BgmZpq6v9cZTK-9R++5AdPCWlAM1K-d zi2JkC{-poG0)+rq7#>@4${>x`Yt;EmYV8$IPS5)hnOMx`{B8U%<6F^~`}IwQH;5i!mC`8+>`5_;37oZRAibWtKh{ zIyG-E9jv;3zV9y1aK zNUn|DsJup-vD+lbX?^&lD)tEnL=K&cJ?e`Y=k;D{funMhl5gEgp`V}$yL^dNa7_R0 zDWD^+sPpSjpRp`C1)l;ZD$S7V<^KED^)O;=$CFU+vg}2oq}yq=z)sWx?ulDm3P%AW zJM!l3C;Nb?;01OJ!({CRQH;GfIm3jp8|&98Q*VvS?Zn3HE&q_|DqKW;D|WKA3K#i0 z|8ETS3*%~Mh(%58sMzx7L5LH%HYyN6mQpm?3Hg({^}ljV$rSoShxg(J_VdDmBJM

)?f^N%Ma zTxaXZJ^y>m)N!@UJ`kh-pGZ9}`v>ujC0l`hwIwk0Sj1pOb-gD9%|N+osu2?Lru&Y9 zZX!m#U*et#21-1#v$eyOPpc*{HQNu)(R0tI?{hQ70SD$?b-%&u0||-0u{~H zUmSxLBi2)nz7*TceQn=SigeYwb@6giDYV9{<-1W|>m=RB2WeInzJ{e$nup>NHHjq8 zFCAL1-WVFhTdSC`wCI>X*=Qz6R;JUgf8ij^rS6YWlBYtlByXcl&2+u@Ddmh9P?mnD zKL5{sS9jV|iYO^~2o({)5Ao1&%JYhyp#EgxOA^Va^Y)Co_z146Yh@q!i6ndAO+cSd z9~+~KdyvjxW=!Sh?}2S1i+6T~2)1%k+=-;uy)|Ne57*u!=Z`ypXNSka-Ff(#KO$YK z?p*BK&j9%uUCN0ZZHVPLwj(v>^}`xx-dT*9VJjR@=WP*hLS3EPt?`5&|Eoq|emLm) zl}PjZASw#6<_Kxq<%oPX^?Q|`%U#Yr`OO3LwXdNxDUn%3-O7|L<6^&j{!}pB`!SrJ zw5>4UF#}%dT0Urfbl4jMej)(Pejk*ds2fh(^&{(3)HHJO*}$0xc})BK(%ZW4;!;KOAaecq&bB*% z-(;2hhUo@PI9~(&~I}qYqnO4y@Vu3W1>pTmcEzCzz`=#@qVSe^XByPii)m za-dXYFR|RVeJBbLsBz8Hwhbw6j&0VmW?aTEUERoLUHt4^AIJ3~ z;Fk%t=by~OCYq00q&tq&yz$&Fv=me}@fyC)r<87N586-%@3YTGu>9V`D^c6RW$3;o zfn{|e@(=u^#x?8Bu2`{0ZIY?*|FTPNSHGrbuLyH|;HTrpd z$X}fdxvuX=W0%w2j`{6n7>$DeABW>$z;iBQ7AE>gV^kwhvrdM5ZW1bqOR2er67ECo zHjsOJ`89x>j+YZ`_CVkTtJ+d)mr4+wl<9O35>=4&$jKR=o^V=z^qHm9Zq#=>>C?eb zcPqo*9!zSu9ejIaQIAItBk4a{j!dip&)S9oW}6CjLLZK1lVcDq?R-3wRdR zD-FeJKg_&AO#c9mjsu84FAP{d^h@(pS|gc~yYZ4)T&vbQ;?lm(ER8pObhqVP|C zWEf6j|9t=p7}UDJ z`(b-5RYDci96>=FO<6nWoaN}Mhx=xJqa3gHQFqsk`4o3>K!8f$H84n{{fo(H>cWaU zPb5m0N3faGPA)VRwUu1!OA|Ben-85A_4=z<%fFj@;|7a>>lc({p9pE=1+-+VpDP67 z*JFJfd7I%Gz4mXr1YA3?WaQZ6>r`Ur_C*=riV~wR&aUdH+$)k9jY1Q=8rEd?WciwT zT12F+@2FtKQpZI1Ol{4G2P?@xVg?m8=j3d+fs2$Ukw{aaCEk``3D^k-QTFtSlGE?`hv~eWjI3KYf8M?KWD67CAcyvUPQxbe4h?kvqm%lm9{qn<0Esoa*_vyuobXfO zFY;iRdC0NHmH#?18*&6`E!liK_%a@)MhBeMBnG<`MHzVgEkz|D$Jd0V)y~9Fel6o` z$gm67Z|@&%cC??i5{~cpOs~aI@^HzhCk$a$cCS$*u7TKYk`8TN(y8$VDoLzko=^N?NSr%b zF{1McC9eavHACC{*H&BqF0H4xDR(#wE2q{d>tH32=j!2}hLf@Rli4Dmo0u8FG&m`S zVvp**C$dZZd*rf#7gB#GJ%7N5RTcEBeOtHu3|L7RTNBGe_-a!1bywt8w_HBmFcDn{ zx3z|X!4?kpwfwuI$M2T-m${FKImVuQDlrH``$M;lx{)Y@yXs4s$V!(-Rw`VYL*gMu>&5e&g{C3B^XWE|;w8V6sV z0oFX%ea2&}Z(Xlh=DI;YjKv0PmIitJfqr$Bs^CeGv+U_-w(I3<}F($DO`Ts>RROxyJ3Xw_|DZoMcyig+#;9ti6tAyr)G1x2!!xqxPT#*6w=Eqqt2@Lp@1bk)>(*A-UqVeNKZXx zfr_EX#_f>fretG*lHzF(F`~JHxBrd8V-GnWj`CgpjGST9zhxzxrbBg9-8XIA$Il!~ zogljI&O2S{Y7w^23=+v+Ke_j4sWG`oG{e!pnHT|I^RW7FTO>k|j|s>*sjR0Ze_psU zvU`{D2|MRs9K!J`6D$Q+{RxOiE(9U0Qv%;Dxg zKM#=%v3zGJF0(@jYoHv3`tkuW8*K9G?>_=?lGuy^7+-_aSS5{4pCV9BHefHjt=j71 z`0T-N8T``ZN;mEN)z*RIqP(WcI^)%{0!(;}QWRh8M=Y2va%r&1-Q_6tBD<6{S@|CvWoHXYUK>q^XIYm=kC` zxO$=>uKuPW=18MwfvKIdfD2@fCKn5J>H zdMpV_OM{5VIj5M-fAWs${OgU&#jgmf=XPJaxfA+WO!@zMA|(lOUioDF>vzs|ygheW zpY4TrzNOcY*VNlJ!C(-nO+c=Xz*dsS*TkmFAk!O4)HLLOH3ukA8X~+pt<85VbIOZ~ zdhQq9CBNUX9|)`gjk6k=miPq1iaaJ6X*|1#?yqFkVxn|kl|WmHoiL=y1}ZrIJK+3J z=v~~abm$wL^s5-En%4IhC!e!6CZ_qeU_OCD5B%3e*D2)Yv?E$|R-7wm*T3-7f?G@5 z2lb^cHr=7%#LQ=@`<)U0RN80onEUgym|J&ju7NusYO%yof__L+coVx{J2f(3fmut4Ge-#2> zbo_;U`JCK-Y~(^|iJ*l2pSBuA#?N)txXh70s(rox%{1=0FZUjt{s3~sD6r+%AMDr~ zywoh;C#iP`pufl-I?Akwdrb_7#l}~izs6BD%^~


{dnA%jGV0oM{k;wO#!IXK0q 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%0DFObR)Y)9teS}HY((LzsFbpZ8 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 SB%XNy0000l-Nvr8{fU~#w*|RoKOh`hWWY>+ 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

_~JvG8(1FQt|778O-F2 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..4db2c8a --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,3 @@ + + #ff643c + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml deleted file mode 100644 index d2aa524..0000000 --- a/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/assets/translations/en_En.json b/assets/translations/en-US.json similarity index 96% rename from assets/translations/en_En.json rename to assets/translations/en-US.json index 3552d0d..bdb591d 100644 --- a/assets/translations/en_En.json +++ b/assets/translations/en-US.json @@ -102,5 +102,7 @@ "rideHistory": "Ride History", "plsLoginToAcc": "Please Log In to Continue", "youAreNotLoggedIn": "You’re not logged in. Please sign in to access your account and explore all features.", - "noOrderfound": "No order found" + "noOrderfound": "No order found", + "reset_password_link_sent": "A reset link has been sent to {email}", + "pay_amount": "Pay Amount: {amount}" } \ No newline at end of file diff --git a/assets/translations/ru-RU.json b/assets/translations/ru-RU.json new file mode 100644 index 0000000..bdb591d --- /dev/null +++ b/assets/translations/ru-RU.json @@ -0,0 +1,108 @@ +{ + "loginToExplore" : "Log in to explore your all in one vendor app favourites and shop effortlessly.", + "emailAddress": "Email Address*", + "password": "Password*", + "enterPassword": "Enter password", + "forgotPassword": "Forgot Password", + "login": "Log in", + "orContinueWith": "or continue with", + + + "withGoogle": "with Google", + "withApple": "with Apple", + "dontHaveAccount": "Didn't have an account?", + "signUp": "Sign up", + "skip": "Skip", + "signUpToExplore": "Sign up to explore all our services and start shopping, riding, and more.", + "firstName": "First Name*", + "lastName": "Last Name*", + "enterMobileNumber": "Enter Mobile number", + "confirmPassword": "Confirm Password*", + "enterConfirmPassword": "Enter confirm password", + "referralCode": "Referral Code", + "enterReferralCode": "Enter referral code", + "alreadyHaveAccount":"Already have an account?", + "enterYourregisteredEmail": "Enter your registered email to receive a reset link.", + "sendLink": "Send Link", + "rememberPassword": "Remember Password?", + "enterOtpSent": "Enter the OTP sent to your mobile", + "resendOTP": "Resend OTP", + "verify": "Verify", + "useYourMobileNumber": "Use your mobile number to Log in easily and securely.", + "sendCode":"Send Code", + "serviceIsUnavailable": "Service is unavailable at the selected address.", + "pickUpLocation": "Pickup Location", + "destinationLocation": "Destination Location", + "continueT":"Continue", + "plsSelectSourceLocation": "Please select source location", + "plsSelectDestinationLocations": "Please select destination location", + "selectVehicleType": "Select Your Vehicle Type", + "plsSelectVehicleTypeFirst": "Please select a vehicle type first.", + "plsSelectPaymentMethod": "Please select a payment method", + "insufficientWallet": "Insufficient wallet balance. Please select another payment method.", + "promoCode": "Promo code", + "thisOfferNotEligible": "This offer not eligible for this booking", + "viewAll": "View All", + "writeCoupon": "Write coupon Code", + "redeemNow": "Redeem now", + "plsEnterCouponCode":"Please enter a coupon code", + "couponApplied": "Coupon applied successfully", + "couponExpired": "This coupon code has been expired", + "invalidCouponCode": "Invalid coupon code", + "orderSummary": "Order Summary", + "subtotal": "Subtotal", + "discount": "Discount", + "orderTotal": "Order Total", + "confirmBooking": "Confirm Booking", + "waitingForDriver": "Waiting for driver....", + "cancelRide": "Cancel Ride", + "riderCancelledSucces": "Ride cancelled successfully", + "failedToCancel": "Failed to cancel ride", + "pleaseWait": "Please wait...", + "change": "Change", + "yourSosRequest": "Your SOS request has been submitted to admin", + "yourSosrequestAlreadySubmitted": "Your SOS request is already submitted", + "payNow": "Pay Now", + "youDoNothaveSufficientwalletBalance": "You do not have sufficient wallet balance", + "somethingWentWrong": "Something went wrong, please contact admin.", + "cash": "Cash", + "coupon": "Coupon", + "couponNotFound": "Coupon not found.", + "tapToApply": "Tap To Apply", + "home": "Home", + "myBookings": "My Bookings", + "profile": "profile", + "wallet": "Wallet", + "cabServiceType": "Cab Service Type", + "everyRideVerified": "Every Ride. Every Driver. Verified.", + "allDriversIDCheck": "All drivers go through ID checks and background verification for your safety.", + "intercity": "Intercity", + "aroundTheCity": "Around the city", + "rideDetails": "Ride Details", + "orderId": "Order Id:", + "bookingData": "Booking Date:", + "rideAndFareSummary": "Ride & Fare Summary", + "updateReview": "Update Review", + "addReview": "Add Review", + "complain": "Complain", + "distance": "Distance", + "km": "KM", + "duration": "Duration", + "howWasTrip": "How was your trip?", + "yourFeedbackWillHelp": "Your feedback will help us improve \n driving experience better", + "rateFor": "Rate for", + "typeComment": "Type comment....", + "title": "Title", + "typeDescription": "Type Description...", + "save": "Save", + "popularDestinations": "Popular Destinations", + "selectPaymentMethod": "Select Payment Method", + "prefferedPayment": "Preferred Payment", + "otherPaymentOptions": "Other Payment Options", + "rideHistory": "Ride History", + "plsLoginToAcc": "Please Log In to Continue", + "youAreNotLoggedIn": "You’re not logged in. Please sign in to access your account and explore all features.", + "noOrderfound": "No order found", + "reset_password_link_sent": "A reset link has been sent to {email}", + "pay_amount": "Pay Amount: {amount}" +} \ No newline at end of file diff --git a/assets/translations/ru_RU.json b/assets/translations/ru_RU.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/translations/uz-UZ.json b/assets/translations/uz-UZ.json new file mode 100644 index 0000000..bdb591d --- /dev/null +++ b/assets/translations/uz-UZ.json @@ -0,0 +1,108 @@ +{ + "loginToExplore" : "Log in to explore your all in one vendor app favourites and shop effortlessly.", + "emailAddress": "Email Address*", + "password": "Password*", + "enterPassword": "Enter password", + "forgotPassword": "Forgot Password", + "login": "Log in", + "orContinueWith": "or continue with", + + + "withGoogle": "with Google", + "withApple": "with Apple", + "dontHaveAccount": "Didn't have an account?", + "signUp": "Sign up", + "skip": "Skip", + "signUpToExplore": "Sign up to explore all our services and start shopping, riding, and more.", + "firstName": "First Name*", + "lastName": "Last Name*", + "enterMobileNumber": "Enter Mobile number", + "confirmPassword": "Confirm Password*", + "enterConfirmPassword": "Enter confirm password", + "referralCode": "Referral Code", + "enterReferralCode": "Enter referral code", + "alreadyHaveAccount":"Already have an account?", + "enterYourregisteredEmail": "Enter your registered email to receive a reset link.", + "sendLink": "Send Link", + "rememberPassword": "Remember Password?", + "enterOtpSent": "Enter the OTP sent to your mobile", + "resendOTP": "Resend OTP", + "verify": "Verify", + "useYourMobileNumber": "Use your mobile number to Log in easily and securely.", + "sendCode":"Send Code", + "serviceIsUnavailable": "Service is unavailable at the selected address.", + "pickUpLocation": "Pickup Location", + "destinationLocation": "Destination Location", + "continueT":"Continue", + "plsSelectSourceLocation": "Please select source location", + "plsSelectDestinationLocations": "Please select destination location", + "selectVehicleType": "Select Your Vehicle Type", + "plsSelectVehicleTypeFirst": "Please select a vehicle type first.", + "plsSelectPaymentMethod": "Please select a payment method", + "insufficientWallet": "Insufficient wallet balance. Please select another payment method.", + "promoCode": "Promo code", + "thisOfferNotEligible": "This offer not eligible for this booking", + "viewAll": "View All", + "writeCoupon": "Write coupon Code", + "redeemNow": "Redeem now", + "plsEnterCouponCode":"Please enter a coupon code", + "couponApplied": "Coupon applied successfully", + "couponExpired": "This coupon code has been expired", + "invalidCouponCode": "Invalid coupon code", + "orderSummary": "Order Summary", + "subtotal": "Subtotal", + "discount": "Discount", + "orderTotal": "Order Total", + "confirmBooking": "Confirm Booking", + "waitingForDriver": "Waiting for driver....", + "cancelRide": "Cancel Ride", + "riderCancelledSucces": "Ride cancelled successfully", + "failedToCancel": "Failed to cancel ride", + "pleaseWait": "Please wait...", + "change": "Change", + "yourSosRequest": "Your SOS request has been submitted to admin", + "yourSosrequestAlreadySubmitted": "Your SOS request is already submitted", + "payNow": "Pay Now", + "youDoNothaveSufficientwalletBalance": "You do not have sufficient wallet balance", + "somethingWentWrong": "Something went wrong, please contact admin.", + "cash": "Cash", + "coupon": "Coupon", + "couponNotFound": "Coupon not found.", + "tapToApply": "Tap To Apply", + "home": "Home", + "myBookings": "My Bookings", + "profile": "profile", + "wallet": "Wallet", + "cabServiceType": "Cab Service Type", + "everyRideVerified": "Every Ride. Every Driver. Verified.", + "allDriversIDCheck": "All drivers go through ID checks and background verification for your safety.", + "intercity": "Intercity", + "aroundTheCity": "Around the city", + "rideDetails": "Ride Details", + "orderId": "Order Id:", + "bookingData": "Booking Date:", + "rideAndFareSummary": "Ride & Fare Summary", + "updateReview": "Update Review", + "addReview": "Add Review", + "complain": "Complain", + "distance": "Distance", + "km": "KM", + "duration": "Duration", + "howWasTrip": "How was your trip?", + "yourFeedbackWillHelp": "Your feedback will help us improve \n driving experience better", + "rateFor": "Rate for", + "typeComment": "Type comment....", + "title": "Title", + "typeDescription": "Type Description...", + "save": "Save", + "popularDestinations": "Popular Destinations", + "selectPaymentMethod": "Select Payment Method", + "prefferedPayment": "Preferred Payment", + "otherPaymentOptions": "Other Payment Options", + "rideHistory": "Ride History", + "plsLoginToAcc": "Please Log In to Continue", + "youAreNotLoggedIn": "You’re not logged in. Please sign in to access your account and explore all features.", + "noOrderfound": "No order found", + "reset_password_link_sent": "A reset link has been sent to {email}", + "pay_amount": "Pay Amount: {amount}" +} \ No newline at end of file diff --git a/assets/translations/uz_UZ.json b/assets/translations/uz_UZ.json deleted file mode 100644 index e69de29..0000000 diff --git a/lib/constant/constant.dart b/lib/constant/constant.dart index 4d13a6b..6becfc0 100644 --- a/lib/constant/constant.dart +++ b/lib/constant/constant.dart @@ -19,7 +19,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart' as geolocator; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:intl/intl.dart'; import 'package:mailer/mailer.dart'; @@ -172,7 +172,10 @@ class Constant { static bool checkZoneCheck(double latitude, double longLatitude) { bool isZoneAvailable = false; for (var element in Constant.zoneList) { - if (Constant.isPointInPolygon(LatLng(latitude, longLatitude), element.area!)) { + if (Constant.isPointInPolygon( + LatLng(latitude, longLatitude), + element.area!, + )) { isZoneAvailable = true; break; } else { @@ -185,7 +188,10 @@ class Constant { static String? getZoneId(double latitude, double longLatitude) { String? zoneId; for (var element in Constant.zoneList) { - if (Constant.isPointInPolygon(LatLng(latitude, longLatitude), element.area!)) { + if (Constant.isPointInPolygon( + LatLng(latitude, longLatitude), + element.area!, + )) { zoneId = element.id; break; } @@ -198,13 +204,18 @@ class Constant { return (rng.nextInt(900000) + 100000).toString(); // 6 digit } - static Future checkPermission({required BuildContext context, required Function() onTap}) async { + static Future checkPermission({ + required BuildContext context, + required Function() onTap, + }) async { LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); } if (permission == LocationPermission.denied) { - ShowToastDialog.showToast("You have to allow location permission to use your location"); + ShowToastDialog.showToast( + "You have to allow location permission to use your location", + ); } else if (permission == LocationPermission.deniedForever) { showDialog( context: context, @@ -241,7 +252,10 @@ class Constant { return isPlanExpire; } - static bool isExpireDate({required bool expiryDay, Timestamp? subscriptionExpiryDate}) { + static bool isExpireDate({ + required bool expiryDay, + Timestamp? subscriptionExpiryDate, + }) { bool isPlanExpire = false; if (expiryDay == true) { isPlanExpire = false; @@ -301,17 +315,49 @@ class Constant { String commission = "0"; if (sectionConstantModel!.adminCommision!.isEnabled == true) { if (vendorModel.adminCommission == null) { - if (sectionConstantModel!.adminCommision!.commissionType!.toLowerCase() == "Percent".toLowerCase() || - sectionConstantModel!.adminCommision!.commissionType?.toLowerCase() == "Percentage".toLowerCase()) { - commission = (double.parse(price) + (double.parse(price) * double.parse(sectionConstantModel!.adminCommision!.amount.toString()) / 100)).toString(); + if (sectionConstantModel!.adminCommision!.commissionType! + .toLowerCase() == + "Percent".toLowerCase() || + sectionConstantModel!.adminCommision!.commissionType + ?.toLowerCase() == + "Percentage".toLowerCase()) { + commission = + (double.parse(price) + + (double.parse(price) * + double.parse( + sectionConstantModel!.adminCommision!.amount + .toString(), + ) / + 100)) + .toString(); } else { - commission = (double.parse(price) + double.parse(sectionConstantModel!.adminCommision!.amount.toString())).toString(); + commission = + (double.parse(price) + + double.parse( + sectionConstantModel!.adminCommision!.amount.toString(), + )) + .toString(); } } else { - if (vendorModel.adminCommission!.commissionType!.toLowerCase() == "Percent".toLowerCase() || vendorModel.adminCommission!.commissionType?.toLowerCase() == "Percentage".toLowerCase()) { - commission = (double.parse(price) + (double.parse(price) * double.parse(vendorModel.adminCommission!.amount.toString()) / 100)).toString(); + if (vendorModel.adminCommission!.commissionType!.toLowerCase() == + "Percent".toLowerCase() || + vendorModel.adminCommission!.commissionType?.toLowerCase() == + "Percentage".toLowerCase()) { + commission = + (double.parse(price) + + (double.parse(price) * + double.parse( + vendorModel.adminCommission!.amount.toString(), + ) / + 100)) + .toString(); } else { - commission = (double.parse(price) + double.parse(vendorModel.adminCommission!.amount.toString())).toString(); + commission = + (double.parse(price) + + double.parse( + vendorModel.adminCommission!.amount.toString(), + )) + .toString(); } } } else { @@ -327,7 +373,10 @@ class Constant { if (taxModel.type == "fix") { taxAmount = double.parse(taxModel.tax.toString()); } else { - taxAmount = (double.parse(amount.toString()) * double.parse(taxModel.tax!.toString())) / 100; + taxAmount = + (double.parse(amount.toString()) * + double.parse(taxModel.tax!.toString())) / + 100; } } return taxAmount; @@ -336,8 +385,12 @@ class Constant { static double calculateDiscount({String? amount, CouponModel? offerModel}) { double taxAmount = 0.0; if (offerModel != null) { - if (offerModel.discountType == "Percentage" || offerModel.discountType == "percentage") { - taxAmount = (double.parse(amount.toString()) * double.parse(offerModel.discount.toString())) / 100; + if (offerModel.discountType == "Percentage" || + offerModel.discountType == "percentage") { + taxAmount = + (double.parse(amount.toString()) * + double.parse(offerModel.discount.toString())) / + 100; } else { taxAmount = double.parse(offerModel.discount.toString()); } @@ -345,11 +398,17 @@ class Constant { return taxAmount; } - static String calculateReview({required String? reviewCount, required String? reviewSum}) { - if (0 == double.parse(reviewSum.toString()) && 0 == double.parse(reviewSum.toString())) { + static String calculateReview({ + required String? reviewCount, + required String? reviewSum, + }) { + if (0 == double.parse(reviewSum.toString()) && + 0 == double.parse(reviewSum.toString())) { return "0"; } - return (double.parse(reviewSum.toString()) / double.parse(reviewCount.toString())).toStringAsFixed(1); + return (double.parse(reviewSum.toString()) / + double.parse(reviewCount.toString())) + .toStringAsFixed(1); } static String getUuid() { @@ -357,13 +416,24 @@ class Constant { } static Widget loader() { - return Center(child: CircularProgressIndicator(color: AppThemeData.primary300)); + return Center( + child: CircularProgressIndicator(color: AppThemeData.primary300), + ); } static Widget showEmptyView({required String message}) { final themeController = Get.find(); final isDark = themeController.isDark.value; - return Center(child: Text(message, style: TextStyle(fontFamily: AppThemeData.fontFamily, fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))); + return Center( + child: Text( + message, + style: TextStyle( + fontFamily: AppThemeData.fontFamily, + fontSize: 18, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + ); } static String maskingString(String documentId, int maskingDigit) { @@ -382,7 +452,8 @@ class Constant { } String? validateEmail(String? value) { - String pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; + String pattern = + r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; RegExp regExp = RegExp(pattern); if (value == null || value.isEmpty) { return "Email is Required"; @@ -393,9 +464,19 @@ class Constant { } } - static String getDistance({required String lat1, required String lng1, required String lat2, required String lng2}) { + static String getDistance({ + required String lat1, + required String lng1, + required String lat2, + required String lng2, + }) { double distance; - double distanceInMeters = Geolocator.distanceBetween(double.parse(lat1), double.parse(lng1), double.parse(lat2), double.parse(lng2)); + double distanceInMeters = Geolocator.distanceBetween( + double.parse(lat1), + double.parse(lng1), + double.parse(lat2), + double.parse(lng2), + ); if (distanceType == "miles") { distance = distanceInMeters / 1609; } else { @@ -405,7 +486,8 @@ class Constant { } bool hasValidUrl(String? value) { - String pattern = r'(http|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?'; + String pattern = + r'(http|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?'; RegExp regExp = RegExp(pattern); if (value == null || value.isEmpty) { return false; @@ -415,10 +497,17 @@ class Constant { return true; } - static Future uploadUserImageToFireStorage(File image, String filePath, String fileName) async { - Reference upload = FirebaseStorage.instance.ref().child('$filePath/$fileName'); + static Future uploadUserImageToFireStorage( + File image, + String filePath, + String fileName, + ) async { + Reference upload = FirebaseStorage.instance.ref().child( + '$filePath/$fileName', + ); UploadTask uploadTask = upload.putFile(image); - var downloadUrl = await (await uploadTask.whenComplete(() {})).ref.getDownloadURL(); + var downloadUrl = + await (await uploadTask.whenComplete(() {})).ref.getDownloadURL(); return downloadUrl.toString(); } @@ -435,14 +524,22 @@ class Constant { Future getBytesFromAsset(String path, int width) async { ByteData data = await rootBundle.load(path); - ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width); + ui.Codec codec = await ui.instantiateImageCodec( + data.buffer.asUint8List(), + targetWidth: width, + ); ui.FrameInfo fi = await codec.getNextFrame(); - return (await fi.image.toByteData(format: ui.ImageByteFormat.png))!.buffer.asUint8List(); + return (await fi.image.toByteData( + format: ui.ImageByteFormat.png, + ))!.buffer.asUint8List(); } static Future selectTime(context) async { FocusScope.of(context).requestFocus(FocusNode()); //remove focus - TimeOfDay? newTime = await showTimePicker(context: context, initialTime: TimeOfDay.now()); + TimeOfDay? newTime = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ); if (newTime != null) { return newTime; } @@ -480,7 +577,11 @@ class Constant { static int calculateDifference(DateTime date) { DateTime now = DateTime.now(); - return DateTime(date.year, date.month, date.day).difference(DateTime(now.year, now.month, now.day)).inDays; + return DateTime( + date.year, + date.month, + date.day, + ).difference(DateTime(now.year, now.month, now.day)).inDays; } static String timestampToDate(Timestamp timestamp) { @@ -509,7 +610,15 @@ class Constant { } static DateTime stringToDate(String openDineTime) { - return DateFormat('HH:mm').parse(DateFormat('HH:mm').format(DateFormat("hh:mm a").parse((Intl.getCurrentLocale() == "en_US") ? openDineTime : openDineTime.toLowerCase()))); + return DateFormat('HH:mm').parse( + DateFormat('HH:mm').format( + DateFormat("hh:mm a").parse( + (Intl.getCurrentLocale() == "en_US") + ? openDineTime + : openDineTime.toLowerCase(), + ), + ), + ); } static LanguageModel getLanguage() { @@ -527,7 +636,10 @@ class Constant { int crossings = 0; for (int i = 0; i < polygon.length; i++) { int next = (i + 1) % polygon.length; - if (polygon[i].latitude <= point.latitude && polygon[next].latitude > point.latitude || polygon[i].latitude > point.latitude && polygon[next].latitude <= point.latitude) { + if (polygon[i].latitude <= point.latitude && + polygon[next].latitude > point.latitude || + polygon[i].latitude > point.latitude && + polygon[next].latitude <= point.latitude) { double edgeLong = polygon[next].longitude - polygon[i].longitude; double edgeLat = polygon[next].latitude - polygon[i].latitude; double interpol = (point.latitude - polygon[i].latitude) / edgeLat; @@ -549,7 +661,12 @@ class Constant { allowInsecure: true, ); - static Future sendMail({String? subject, String? body, bool? isAdmin = false, List? recipients}) async { + static Future sendMail({ + String? subject, + String? body, + bool? isAdmin = false, + List? recipients, + }) async { // Create our message. if (mailSettings != null) { if (isAdmin == true) { @@ -557,7 +674,10 @@ class Constant { } final message = Message() - ..from = Address(mailSettings!.userName.toString(), mailSettings!.fromName.toString()) + ..from = Address( + mailSettings!.userName.toString(), + mailSettings!.fromName.toString(), + ) ..recipients = recipients! ..subject = subject ..text = body @@ -581,10 +701,17 @@ class Constant { // await connection.send(message); } - static Uri createCoordinatesUrl(double latitude, double longitude, [String? label]) { + static Uri createCoordinatesUrl( + double latitude, + double longitude, [ + String? label, + ]) { Uri uri; if (kIsWeb) { - uri = Uri.https('www.google.com', '/maps/search/', {'api': '1', 'query': '$latitude,$longitude'}); + uri = Uri.https('www.google.com', '/maps/search/', { + 'api': '1', + 'query': '$latitude,$longitude', + }); } else if (Platform.isAndroid) { var query = '$latitude,$longitude'; if (label != null) query += '($label)'; @@ -594,14 +721,18 @@ class Constant { if (label != null) params['q'] = label; uri = Uri.https('maps.apple.com', '/', params); } else { - uri = Uri.https('www.google.com', '/maps/search/', {'api': '1', 'query': '$latitude,$longitude'}); + uri = Uri.https('www.google.com', '/maps/search/', { + 'api': '1', + 'query': '$latitude,$longitude', + }); } return uri; } static Future sendOrderEmail({required OrderModel orderModel}) async { - EmailTemplateModel? emailTemplateModel = await FireStoreUtils.getEmailTemplates(newOrderPlaced); + EmailTemplateModel? emailTemplateModel = + await FireStoreUtils.getEmailTemplates(newOrderPlaced); if (emailTemplateModel != null) { String firstHTML = """ @@ -618,11 +749,23 @@ class Constant { """; String newString = emailTemplateModel.message.toString(); - newString = newString.replaceAll("{username}", "${Constant.userModel!.firstName} ${Constant.userModel!.lastName}"); + newString = newString.replaceAll( + "{username}", + "${Constant.userModel!.firstName} ${Constant.userModel!.lastName}", + ); newString = newString.replaceAll("{orderid}", orderModel.id.toString()); - newString = newString.replaceAll("{date}", DateFormat('yyyy-MM-dd').format(orderModel.createdAt!.toDate())); - newString = newString.replaceAll("{address}", orderModel.address!.getFullAddress()); - newString = newString.replaceAll("{paymentmethod}", orderModel.paymentMethod.toString()); + newString = newString.replaceAll( + "{date}", + DateFormat('yyyy-MM-dd').format(orderModel.createdAt!.toDate()), + ); + newString = newString.replaceAll( + "{address}", + orderModel.address!.getFullAddress(), + ); + newString = newString.replaceAll( + "{paymentmethod}", + orderModel.paymentMethod.toString(), + ); double deliveryCharge = 0.0; double total = 0.0; @@ -630,7 +773,8 @@ class Constant { double discount = 0.0; double taxAmount = 0.0; double tipValue = 0.0; - String specialLabel = '(${orderModel.specialDiscount!['special_discount_label']}${orderModel.specialDiscount!['specialType'] == "amount" ? currencyModel!.symbol : "%"})'; + String specialLabel = + '(${orderModel.specialDiscount!['special_discount_label']}${orderModel.specialDiscount!['specialType'] == "amount" ? currencyModel!.symbol : "%"})'; List htmlList = []; if (orderModel.deliveryCharge != null) { @@ -640,15 +784,22 @@ class Constant { tipValue = double.parse(orderModel.tipAmount.toString()); } for (var element in orderModel.products!) { - if (element.extrasPrice != null && element.extrasPrice!.isNotEmpty && double.parse(element.extrasPrice!) != 0.0) { - total += double.parse(element.quantity.toString()) * double.parse(element.extrasPrice!); + if (element.extrasPrice != null && + element.extrasPrice!.isNotEmpty && + double.parse(element.extrasPrice!) != 0.0) { + total += + double.parse(element.quantity.toString()) * + double.parse(element.extrasPrice!); } - total += double.parse(element.quantity.toString()) * double.parse(element.price.toString()); + total += + double.parse(element.quantity.toString()) * + double.parse(element.price.toString()); List? addon = element.extras; String extrasDisVal = ''; for (int i = 0; i < addon!.length; i++) { - extrasDisVal += '${addon[i].toString().replaceAll("\"", "")} ${(i == addon.length - 1) ? "" : ","}'; + extrasDisVal += + '${addon[i].toString().replaceAll("\"", "")} ${(i == addon.length - 1) ? "" : ","}'; } String product = """ @@ -666,7 +817,9 @@ class Constant { } if (orderModel.specialDiscount!.isNotEmpty) { - specialDiscount = double.parse(orderModel.specialDiscount!['special_discount'].toString()); + specialDiscount = double.parse( + orderModel.specialDiscount!['special_discount'].toString(), + ); } if (orderModel.couponId != null && orderModel.couponId!.isNotEmpty) { @@ -675,35 +828,81 @@ class Constant { List taxHtmlList = []; for (var element in taxList) { - taxAmount = taxAmount + calculateTax(amount: (total - discount - specialDiscount).toString(), taxModel: element); + taxAmount = + taxAmount + + calculateTax( + amount: (total - discount - specialDiscount).toString(), + taxModel: element, + ); String taxHtml = """${element.title}: ${amountShow(amount: calculateTax(amount: (total - discount - specialDiscount).toString(), taxModel: element).toString())}${taxList.indexOf(element) == taxList.length - 1 ? "" : "
"}"""; taxHtmlList.add(taxHtml); } var totalamount = - orderModel.deliveryCharge == null || orderModel.deliveryCharge!.isEmpty + orderModel.deliveryCharge == null || + orderModel.deliveryCharge!.isEmpty ? total + taxAmount - discount - specialDiscount - : total + taxAmount + double.parse(orderModel.deliveryCharge!) + double.parse(orderModel.tipAmount!) - discount - specialDiscount; + : total + + taxAmount + + double.parse(orderModel.deliveryCharge!) + + double.parse(orderModel.tipAmount!) - + discount - + specialDiscount; - newString = newString.replaceAll("{subtotal}", amountShow(amount: total.toString())); - newString = newString.replaceAll("{coupon}", orderModel.couponId.toString()); - newString = newString.replaceAll("{discountamount}", amountShow(amount: orderModel.discount.toString())); + newString = newString.replaceAll( + "{subtotal}", + amountShow(amount: total.toString()), + ); + newString = newString.replaceAll( + "{coupon}", + orderModel.couponId.toString(), + ); + newString = newString.replaceAll( + "{discountamount}", + amountShow(amount: orderModel.discount.toString()), + ); newString = newString.replaceAll("{specialcoupon}", specialLabel); - newString = newString.replaceAll("{specialdiscountamount}", amountShow(amount: specialDiscount.toString())); - newString = newString.replaceAll("{shippingcharge}", amountShow(amount: deliveryCharge.toString())); - newString = newString.replaceAll("{tipamount}", amountShow(amount: tipValue.toString())); - newString = newString.replaceAll("{totalAmount}", amountShow(amount: totalamount.toString())); + newString = newString.replaceAll( + "{specialdiscountamount}", + amountShow(amount: specialDiscount.toString()), + ); + newString = newString.replaceAll( + "{shippingcharge}", + amountShow(amount: deliveryCharge.toString()), + ); + newString = newString.replaceAll( + "{tipamount}", + amountShow(amount: tipValue.toString()), + ); + newString = newString.replaceAll( + "{totalAmount}", + amountShow(amount: totalamount.toString()), + ); String tableHTML = htmlList.join(); String lastHTML = "
"; - newString = newString.replaceAll("{productdetails}", firstHTML + tableHTML + lastHTML); + newString = newString.replaceAll( + "{productdetails}", + firstHTML + tableHTML + lastHTML, + ); newString = newString.replaceAll("{taxdetails}", taxHtmlList.join()); - newString = newString.replaceAll("{newwalletbalance}.", amountShow(amount: Constant.userModel!.walletAmount.toString())); + newString = newString.replaceAll( + "{newwalletbalance}.", + amountShow(amount: Constant.userModel!.walletAmount.toString()), + ); String subjectNewString = emailTemplateModel.subject.toString(); - subjectNewString = subjectNewString.replaceAll("{orderid}", orderModel.id.toString()); - await sendMail(subject: subjectNewString, isAdmin: emailTemplateModel.isSendToAdmin, body: newString, recipients: [Constant.userModel!.email]); + subjectNewString = subjectNewString.replaceAll( + "{orderid}", + orderModel.id.toString(), + ); + await sendMail( + subject: subjectNewString, + isAdmin: emailTemplateModel.isSendToAdmin, + body: newString, + recipients: [Constant.userModel!.email], + ); } } @@ -711,7 +910,12 @@ class Constant { const R = 6371; // Earth's radius in km final dLat = _degToRad(lat2 - lat1); final dLon = _degToRad(lon2 - lon1); - final a = sin(dLat / 2) * sin(dLat / 2) + cos(_degToRad(lat1)) * cos(_degToRad(lat2)) * sin(dLon / 2) * sin(dLon / 2); + final a = + sin(dLat / 2) * sin(dLat / 2) + + cos(_degToRad(lat1)) * + cos(_degToRad(lat2)) * + sin(dLon / 2) * + sin(dLon / 2); final c = 2 * atan2(sqrt(a), sqrt(1 - a)); return R * c; } @@ -725,13 +929,19 @@ class Constant { } /// Calculate tax amount for a single tax model - static double getTaxValue({required String amount, required TaxModel taxModel}) { + static double getTaxValue({ + required String amount, + required TaxModel taxModel, + }) { double taxVal = 0.0; if (taxModel.enable == true) { if (taxModel.type == "fix") { taxVal = double.tryParse(taxModel.tax.toString()) ?? 0.0; } else { - taxVal = (double.tryParse(amount) ?? 0.0) * (double.tryParse(taxModel.tax.toString()) ?? 0.0) / 100; + taxVal = + (double.tryParse(amount) ?? 0.0) * + (double.tryParse(taxModel.tax.toString()) ?? 0.0) / + 100; } } return taxVal; @@ -743,10 +953,15 @@ class Constant { if (response.statusCode != 200) throw Exception("Failed to load image"); final Uint8List bytes = response.bodyBytes; - final ui.Codec codec = await ui.instantiateImageCodec(bytes, targetWidth: width); + final ui.Codec codec = await ui.instantiateImageCodec( + bytes, + targetWidth: width, + ); final ui.FrameInfo frameInfo = await codec.getNextFrame(); - final ByteData? byteData = await frameInfo.image.toByteData(format: ui.ImageByteFormat.png); + final ByteData? byteData = await frameInfo.image.toByteData( + format: ui.ImageByteFormat.png, + ); return byteData!.buffer.asUint8List(); } catch (e) { print("⚠️ getBytesFromUrl error: $e — using default cab icon"); diff --git a/lib/controllers/0n_demand_payment_controller.dart b/lib/controllers/0n_demand_payment_controller.dart index 6a8e3cd..e53d848 100644 --- a/lib/controllers/0n_demand_payment_controller.dart +++ b/lib/controllers/0n_demand_payment_controller.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import '../../models/onprovider_order_model.dart'; import '../models/wallet_transaction_model.dart'; @@ -48,7 +48,9 @@ import '../utils/preferences.dart'; import 'on_demand_dashboard_controller.dart'; class OnDemandPaymentController extends GetxController { - Rx onDemandOrderModel = Rx(null); + Rx onDemandOrderModel = Rx( + null, + ); RxDouble totalAmount = 0.0.obs; late bool isExtra; @@ -76,19 +78,37 @@ class OnDemandPaymentController extends GetxController { ShowToastDialog.showLoader("Please wait...".tr()); onDemandOrderModel.value?.payment_method = selectedPaymentMethod.value; - onDemandOrderModel.value?.paymentStatus = onDemandOrderModel.value?.provider.priceUnit == "Fixed" && selectedPaymentMethod.value == "cod" ? false : true; + onDemandOrderModel.value?.paymentStatus = + onDemandOrderModel.value?.provider.priceUnit == "Fixed" && + selectedPaymentMethod.value == "cod" + ? false + : true; onDemandOrderModel.value?.extraPaymentStatus = true; - await FireStoreUtils.onDemandOrderPlace(onDemandOrderModel.value!, totalAmount.value); + await FireStoreUtils.onDemandOrderPlace( + onDemandOrderModel.value!, + totalAmount.value, + ); if (onDemandOrderModel.value?.status == Constant.orderPlaced) { - await FireStoreUtils.sendOrderOnDemandServiceEmail(orderModel: onDemandOrderModel.value!); + await FireStoreUtils.sendOrderOnDemandServiceEmail( + orderModel: onDemandOrderModel.value!, + ); - final providerUser = await FireStoreUtils.getUserProfile(onDemandOrderModel.value!.provider.author!); + final providerUser = await FireStoreUtils.getUserProfile( + onDemandOrderModel.value!.provider.author!, + ); if (providerUser != null) { - final payLoad = {"type": 'provider_order', "orderId": onDemandOrderModel.value?.id}; - await SendNotification.sendFcmMessage(Constant.bookingPlaced, providerUser.fcmToken ?? '', payLoad); + final payLoad = { + "type": 'provider_order', + "orderId": onDemandOrderModel.value?.id, + }; + await SendNotification.sendFcmMessage( + Constant.bookingPlaced, + providerUser.fcmToken ?? '', + payLoad, + ); } ShowToastDialog.showToast("OnDemand Service successfully booked".tr()); @@ -107,16 +127,23 @@ class OnDemandPaymentController extends GetxController { paymentStatus: "success".tr(), ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()).then((value) {}); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ).then((value) {}); } }); } ShowToastDialog.closeLoader(); Get.offAll(const OnDemandDashboardScreen()); - OnDemandDashboardController controller = Get.put(OnDemandDashboardController()); + OnDemandDashboardController controller = Get.put( + OnDemandDashboardController(), + ); controller.selectedIndex.value = 2; } else { // Extra Charges Flow @@ -137,9 +164,14 @@ class OnDemandPaymentController extends GetxController { paymentStatus: "success".tr(), ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()).then((value) {}); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ).then((value) {}); } }); } @@ -160,9 +192,14 @@ class OnDemandPaymentController extends GetxController { paymentStatus: "success".tr(), ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-$totalAmount", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: "-$totalAmount", + userId: FireStoreUtils.getCurrentUid(), + ); } }); } @@ -171,7 +208,9 @@ class OnDemandPaymentController extends GetxController { ShowToastDialog.closeLoader(); Get.offAll(const OnDemandDashboardScreen()); - OnDemandDashboardController controller = Get.put(OnDemandDashboardController()); + OnDemandDashboardController controller = Get.put( + OnDemandDashboardController(), + ); controller.selectedIndex.value = 2; } } @@ -194,19 +233,45 @@ class OnDemandPaymentController extends GetxController { Future getPaymentSettings() async { isLoading.value = true; await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -249,20 +314,32 @@ class OnDemandPaymentController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -308,7 +385,10 @@ class OnDemandPaymentController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -318,8 +398,14 @@ class OnDemandPaymentController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -332,12 +418,20 @@ class OnDemandPaymentController extends GetxController { }, ], "payer": {"email": Constant.userModel?.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, "auto_return": "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -420,15 +514,23 @@ class OnDemandPaymentController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -436,15 +538,24 @@ class OnDemandPaymentController extends GetxController { "currency": "NGN", "redirect_url": "${Constant.globalUrl}payment/success", "payment_options": "ussd, card, barter, payattitude", - "customer": {"email": Constant.userModel?.email.toString(), "phonenumber": Constant.userModel?.phoneNumber, "name": Constant.userModel?.fullName()}, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customer": { + "email": Constant.userModel?.email.toString(), + "phonenumber": Constant.userModel?.phoneNumber, + "name": Constant.userModel?.fullName(), + }, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -473,8 +584,14 @@ class OnDemandPaymentController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: Constant.userModel!).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: Constant.userModel!, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -494,26 +611,50 @@ class OnDemandPaymentController extends GetxController { final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString()}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + }, ); final data = jsonDecode(response.body); - await verifyCheckSum(checkSum: data["code"], amount: amount, orderId: orderId).then((value) { + await verifyCheckSum( + checkSum: data["code"], + amount: amount, + orderId: orderId, + ).then((value) { initiatePayment(amount: amount, orderId: orderId).then((value) { String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } GetPaymentTxtTokenModel result = value; - startTransaction(context, txnTokenBy: result.body.txnToken ?? '', orderId: orderId, amount: amount, callBackURL: callback, isStaging: paytmModel.value.isSandboxEnabled); + startTransaction( + context, + txnTokenBy: result.body.txnToken ?? '', + orderId: orderId, + amount: amount, + callBackURL: callback, + isStaging: paytmModel.value.isSandboxEnabled, + ); }); }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -549,24 +690,38 @@ class OnDemandPaymentController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), "checksum_value": checkSum}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -584,9 +739,12 @@ class OnDemandPaymentController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -604,7 +762,10 @@ class OnDemandPaymentController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': Constant.userModel?.phoneNumber, 'email': Constant.userModel?.email}, + 'prefill': { + 'contact': Constant.userModel?.phoneNumber, + 'email': Constant.userModel?.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -639,7 +800,10 @@ class OnDemandPaymentController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -657,15 +821,30 @@ class OnDemandPaymentController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -673,7 +852,9 @@ class OnDemandPaymentController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -692,16 +873,33 @@ class OnDemandPaymentController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString().isNotEmpty) { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -712,13 +910,22 @@ class OnDemandPaymentController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth ?? ''}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth ?? ''}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -731,21 +938,36 @@ class OnDemandPaymentController extends GetxController { return ''; } - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; // ✅ Null-safe handling bool isSandbox = orangeMoneyModel.value.isSandbox ?? false; - String apiUrl = isSandbox ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + isSandbox + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', @@ -761,7 +983,11 @@ class OnDemandPaymentController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -774,7 +1000,9 @@ class OnDemandPaymentController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -888,7 +1116,13 @@ class OnDemandPaymentController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -905,7 +1139,9 @@ class OnDemandPaymentController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -918,7 +1154,11 @@ class OnDemandPaymentController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/Intercity_home_controller.dart b/lib/controllers/Intercity_home_controller.dart index 20fef19..ba768de 100644 --- a/lib/controllers/Intercity_home_controller.dart +++ b/lib/controllers/Intercity_home_controller.dart @@ -48,7 +48,7 @@ import 'package:flutter_map/flutter_map.dart' as flutterMap; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_polyline_points/flutter_polyline_points.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; import 'package:latlong2/latlong.dart' as latlong; @@ -65,10 +65,13 @@ class IntercityHomeController extends GetxController { late GoogleMapController mapController; final flutterMap.MapController mapOsmController = flutterMap.MapController(); - final Rx sourceTextEditController = TextEditingController().obs; - final Rx destinationTextEditController = TextEditingController().obs; + final Rx sourceTextEditController = + TextEditingController().obs; + final Rx destinationTextEditController = + TextEditingController().obs; - final Rx couponCodeTextEditController = TextEditingController().obs; + final Rx couponCodeTextEditController = + TextEditingController().obs; final Rx currentLocation = Location().obs; @@ -142,64 +145,99 @@ class IntercityHomeController extends GetxController { await getPaymentSettings(); - FireStoreUtils.fireStore.collection(CollectionName.users).doc(FireStoreUtils.getCurrentUid()).snapshots().listen((userSnapshot) async { - if (!userSnapshot.exists) return; + FireStoreUtils.fireStore + .collection(CollectionName.users) + .doc(FireStoreUtils.getCurrentUid()) + .snapshots() + .listen((userSnapshot) async { + if (!userSnapshot.exists) return; - userModel.value = UserModel.fromJson(userSnapshot.data()!); + userModel.value = UserModel.fromJson(userSnapshot.data()!); - if (userModel.value.inProgressOrderID != null && userModel.value.inProgressOrderID!.isNotEmpty) { - String? validRideId; + if (userModel.value.inProgressOrderID != null && + userModel.value.inProgressOrderID!.isNotEmpty) { + String? validRideId; - for (String id in userModel.value.inProgressOrderID!) { - final rideDoc = await FireStoreUtils.fireStore.collection(CollectionName.rides).doc(id).get(); + for (String id in userModel.value.inProgressOrderID!) { + final rideDoc = + await FireStoreUtils.fireStore + .collection(CollectionName.rides) + .doc(id) + .get(); - if (rideDoc.exists && (rideDoc.data()?['rideType'] ?? '').toString().toLowerCase() == "intercity") { - validRideId = userModel.value.inProgressOrderID!.first!; - break; - } - } - - FireStoreUtils.fireStore.collection(CollectionName.rides).doc(validRideId).snapshots().listen((rideSnapshot) async { - if (!rideSnapshot.exists) return; - - final rideData = rideSnapshot.data()!; - currentOrder.value = CabOrderModel.fromJson(rideData); - final status = currentOrder.value.status; - - if (status == Constant.driverAccepted || status == Constant.orderInTransit) { - FireStoreUtils.fireStore.collection(CollectionName.users).doc(currentOrder.value.driverId).snapshots().listen((event) async { - if (event.exists && event.data() != null) { - UserModel driverModel0 = UserModel.fromJson(event.data()!); - driverModel.value = driverModel0; - await updateDriverRoute(driverModel0); + if (rideDoc.exists && + (rideDoc.data()?['rideType'] ?? '') + .toString() + .toLowerCase() == + "intercity") { + validRideId = userModel.value.inProgressOrderID!.first!; + break; } - }); - } + } - print("Current Ride Status: $status"); - if (status == Constant.orderPlaced || status == Constant.driverPending || status == Constant.driverRejected || (status == Constant.orderAccepted && currentOrder.value.driverId == null)) { - bottomSheetType.value = 'waitingForDriver'; - } else if (status == Constant.driverAccepted || status == Constant.orderInTransit) { - bottomSheetType.value = 'driverDetails'; - sourceTextEditController.value.text = currentOrder.value.sourceLocationName ?? ''; - destinationTextEditController.value.text = currentOrder.value.destinationLocationName ?? ''; - selectedPaymentMethod.value = currentOrder.value.paymentMethod ?? ''; - calculateTotalAmountAfterAccept(); - } else if (status == Constant.orderCompleted) { - userModel.value.inProgressOrderID!.remove(validRideId); - await FireStoreUtils.updateUser(userModel.value); + FireStoreUtils.fireStore + .collection(CollectionName.rides) + .doc(validRideId) + .snapshots() + .listen((rideSnapshot) async { + if (!rideSnapshot.exists) return; + + final rideData = rideSnapshot.data()!; + currentOrder.value = CabOrderModel.fromJson(rideData); + final status = currentOrder.value.status; + + if (status == Constant.driverAccepted || + status == Constant.orderInTransit) { + FireStoreUtils.fireStore + .collection(CollectionName.users) + .doc(currentOrder.value.driverId) + .snapshots() + .listen((event) async { + if (event.exists && event.data() != null) { + UserModel driverModel0 = UserModel.fromJson( + event.data()!, + ); + driverModel.value = driverModel0; + await updateDriverRoute(driverModel0); + } + }); + } + + print("Current Ride Status: $status"); + if (status == Constant.orderPlaced || + status == Constant.driverPending || + status == Constant.driverRejected || + (status == Constant.orderAccepted && + currentOrder.value.driverId == null)) { + bottomSheetType.value = 'waitingForDriver'; + } else if (status == Constant.driverAccepted || + status == Constant.orderInTransit) { + bottomSheetType.value = 'driverDetails'; + sourceTextEditController.value.text = + currentOrder.value.sourceLocationName ?? ''; + destinationTextEditController.value.text = + currentOrder.value.destinationLocationName ?? ''; + selectedPaymentMethod.value = + currentOrder.value.paymentMethod ?? ''; + calculateTotalAmountAfterAccept(); + } else if (status == Constant.orderCompleted) { + userModel.value.inProgressOrderID!.remove(validRideId); + await FireStoreUtils.updateUser(userModel.value); + bottomSheetType.value = 'location'; + Get.back(); + } + }); + } else { bottomSheetType.value = 'location'; - Get.back(); + if (Constant.currentLocation != null) { + setDepartureMarker( + Constant.currentLocation!.latitude, + Constant.currentLocation!.longitude, + ); + searchPlaceNameOSM(); + } } }); - } else { - bottomSheetType.value = 'location'; - if (Constant.currentLocation != null) { - setDepartureMarker(Constant.currentLocation!.latitude, Constant.currentLocation!.longitude); - searchPlaceNameOSM(); - } - } - }); final coupons = await FireStoreUtils.getCabCoupon(); cabCouponList.value = coupons; @@ -226,18 +264,30 @@ class IntercityHomeController extends GetxController { if (order.status == Constant.driverAccepted) { // DRIVER → PICKUP - await fetchRouteWithWaypoints([latlong.LatLng(driverLat, driverLng), latlong.LatLng(pickupLat, pickupLng)]); + await fetchRouteWithWaypoints([ + latlong.LatLng(driverLat, driverLng), + latlong.LatLng(pickupLat, pickupLng), + ]); } else if (order.status == Constant.orderInTransit) { // PICKUP → DESTINATION - await fetchRouteWithWaypoints([latlong.LatLng(pickupLat, pickupLng), latlong.LatLng(destLat, destLng)]); + await fetchRouteWithWaypoints([ + latlong.LatLng(pickupLat, pickupLng), + latlong.LatLng(destLat, destLng), + ]); } updateRouteMarkers(driverModel); } else { /// For Google Maps if (order.status == Constant.driverAccepted) { - await fetchGoogleRouteBetween(LatLng(driverLat, driverLng), LatLng(pickupLat, pickupLng)); + await fetchGoogleRouteBetween( + LatLng(driverLat, driverLng), + LatLng(pickupLat, pickupLng), + ); } else if (order.status == Constant.orderInTransit) { - await fetchGoogleRouteBetween(LatLng(pickupLat, pickupLng), LatLng(destLat, destLng)); + await fetchGoogleRouteBetween( + LatLng(pickupLat, pickupLng), + LatLng(destLat, destLng), + ); } updateRouteMarkers(driverModel); } @@ -261,12 +311,24 @@ class IntercityHomeController extends GetxController { markers.clear(); osmMarker.clear(); - final departureBytes = await Constant().getBytesFromAsset('assets/images/location_black3x.png', 50); - final destinationBytes = await Constant().getBytesFromAsset('assets/images/location_orange3x.png', 50); + final departureBytes = await Constant().getBytesFromAsset( + 'assets/images/location_black3x.png', + 50, + ); + final destinationBytes = await Constant().getBytesFromAsset( + 'assets/images/location_orange3x.png', + 50, + ); final driverBytesRaw = (Constant.sectionConstantModel?.markerIcon?.isNotEmpty ?? false) - ? await Constant().getBytesFromUrl(Constant.sectionConstantModel!.markerIcon!, width: 120) - : await Constant().getBytesFromAsset('assets/images/ic_cab.png', 50); + ? await Constant().getBytesFromUrl( + Constant.sectionConstantModel!.markerIcon!, + width: 120, + ) + : await Constant().getBytesFromAsset( + 'assets/images/ic_cab.png', + 50, + ); departureIcon = BitmapDescriptor.fromBytes(departureBytes); destinationIcon = BitmapDescriptor.fromBytes(destinationBytes); @@ -275,7 +337,15 @@ class IntercityHomeController extends GetxController { if (Constant.selectedMapType == 'osm') { if (order.status == Constant.driverAccepted) { osmMarker.addAll([ - flutterMap.Marker(point: latlong.LatLng(pickupLat, pickupLng), width: 40, height: 40, child: Image.asset('assets/images/location_black3x.png', width: 40)), + flutterMap.Marker( + point: latlong.LatLng(pickupLat, pickupLng), + width: 40, + height: 40, + child: Image.asset( + 'assets/images/location_black3x.png', + width: 40, + ), + ), flutterMap.Marker( point: latlong.LatLng(driverLat, driverLng), width: 45, @@ -286,13 +356,26 @@ class IntercityHomeController extends GetxController { height: 50, imageUrl: Constant.sectionConstantModel!.markerIcon.toString(), placeholder: (context, url) => Constant.loader(), - errorWidget: (context, url, error) => SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 2)), + errorWidget: + (context, url, error) => SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator(strokeWidth: 2), + ), ), ), ]); } else if (order.status == Constant.orderInTransit) { osmMarker.addAll([ - flutterMap.Marker(point: latlong.LatLng(destLat, destLng), width: 40, height: 40, child: Image.asset('assets/images/location_orange3x.png', width: 40)), + flutterMap.Marker( + point: latlong.LatLng(destLat, destLng), + width: 40, + height: 40, + child: Image.asset( + 'assets/images/location_orange3x.png', + width: 40, + ), + ), flutterMap.Marker( point: latlong.LatLng(driverLat, driverLng), width: 45, @@ -303,7 +386,12 @@ class IntercityHomeController extends GetxController { height: 50, imageUrl: Constant.sectionConstantModel!.markerIcon.toString(), placeholder: (context, url) => Constant.loader(), - errorWidget: (context, url, error) => SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 2)), + errorWidget: + (context, url, error) => SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator(strokeWidth: 2), + ), ), ), ]); @@ -315,9 +403,18 @@ class IntercityHomeController extends GetxController { markerId: const MarkerId("pickup"), position: LatLng(pickupLat, pickupLng), infoWindow: InfoWindow(title: "Pickup Location".tr()), - icon: departureIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen), + icon: + departureIcon ?? + BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueGreen, + ), + ), + Marker( + markerId: const MarkerId("driver"), + position: LatLng(driverLat, driverLng), + infoWindow: InfoWindow(title: "Driver at Pickup".tr()), + icon: taxiIcon ?? BitmapDescriptor.defaultMarker, ), - Marker(markerId: const MarkerId("driver"), position: LatLng(driverLat, driverLng), infoWindow: InfoWindow(title: "Driver at Pickup".tr()), icon: taxiIcon ?? BitmapDescriptor.defaultMarker), ]); } else if (order.status == Constant.orderInTransit) { markers.addAll([ @@ -325,9 +422,18 @@ class IntercityHomeController extends GetxController { markerId: const MarkerId("destination"), position: LatLng(destLat, destLng), infoWindow: InfoWindow(title: "Destination Location".tr()), - icon: destinationIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed), + icon: + destinationIcon ?? + BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueRed, + ), + ), + Marker( + markerId: const MarkerId("driver"), + position: LatLng(driverLat, driverLng), + infoWindow: InfoWindow(title: "Driver Location".tr()), + icon: taxiIcon ?? BitmapDescriptor.defaultMarker, ), - Marker(markerId: const MarkerId("driver"), position: LatLng(driverLat, driverLng), infoWindow: InfoWindow(title: "Driver Location".tr()), icon: taxiIcon ?? BitmapDescriptor.defaultMarker), ]); } } @@ -338,7 +444,10 @@ class IntercityHomeController extends GetxController { } } - Future fetchGoogleRouteBetween(LatLng originPoint, LatLng destPoint) async { + Future fetchGoogleRouteBetween( + LatLng originPoint, + LatLng destPoint, + ) async { final origin = '${originPoint.latitude},${originPoint.longitude}'; final destination = '${destPoint.latitude},${destPoint.longitude}'; final url = Uri.parse( @@ -355,7 +464,8 @@ class IntercityHomeController extends GetxController { final route = data['routes'][0]; final encodedPolyline = route['overview_polyline']['points']; final decodedPoints = PolylinePoints.decodePolyline(encodedPolyline); - final coordinates = decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); + final coordinates = + decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); addPolyLine(coordinates); @@ -382,7 +492,12 @@ class IntercityHomeController extends GetxController { if (currentOrder.value.taxSetting != null) { for (var element in currentOrder.value.taxSetting!) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } } @@ -398,11 +513,19 @@ class IntercityHomeController extends GetxController { subTotal.value = getAmount(selectedVehicleType.value); if (selectedCouponModel.value.id != null) { - discount.value = Constant.calculateDiscount(amount: subTotal.value.toString(), offerModel: selectedCouponModel.value); + discount.value = Constant.calculateDiscount( + amount: subTotal.value.toString(), + offerModel: selectedCouponModel.value, + ); } for (var element in Constant.taxList) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } totalAmount.value = (subTotal.value - discount.value) + taxAmount.value; @@ -439,9 +562,14 @@ class IntercityHomeController extends GetxController { serviceType: Constant.parcelServiceType, ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ); } }); } @@ -455,13 +583,25 @@ class IntercityHomeController extends GetxController { Future placeOrder() async { DestinationLocation sourceLocation = DestinationLocation( - latitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.latitude : departureLatLong.value.latitude, - longitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.longitude : departureLatLong.value.longitude, + latitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.latitude + : departureLatLong.value.latitude, + longitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.longitude + : departureLatLong.value.longitude, ); DestinationLocation destinationLocation = DestinationLocation( - latitude: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value.latitude : destinationLatLong.value.latitude, - longitude: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value.longitude : destinationLatLong.value.longitude, + latitude: + Constant.selectedMapType == 'osm' + ? destinationLatLongOsm.value.latitude + : destinationLatLong.value.latitude, + longitude: + Constant.selectedMapType == 'osm' + ? destinationLatLongOsm.value.longitude + : destinationLatLong.value.longitude, ); CabOrderModel orderModel = CabOrderModel(); @@ -472,7 +612,8 @@ class IntercityHomeController extends GetxController { orderModel.vehicleType = selectedVehicleType.value; orderModel.authorID = FireStoreUtils.getCurrentUid(); orderModel.sourceLocationName = sourceTextEditController.value.text; - orderModel.destinationLocationName = destinationTextEditController.value.text; + orderModel.destinationLocationName = + destinationTextEditController.value.text; orderModel.sourceLocation = sourceLocation; orderModel.destinationLocation = destinationLocation; @@ -484,11 +625,14 @@ class IntercityHomeController extends GetxController { orderModel.taxSetting = Constant.taxList; orderModel.adminCommissionType = - Constant.sectionConstantModel!.adminCommision != null && Constant.sectionConstantModel!.adminCommision!.isEnabled == true - ? Constant.sectionConstantModel!.adminCommision!.commissionType.toString() + Constant.sectionConstantModel!.adminCommision != null && + Constant.sectionConstantModel!.adminCommision!.isEnabled == true + ? Constant.sectionConstantModel!.adminCommision!.commissionType + .toString() : null; orderModel.adminCommission = - Constant.sectionConstantModel!.adminCommision != null && Constant.sectionConstantModel!.adminCommision!.isEnabled == true + Constant.sectionConstantModel!.adminCommision != null && + Constant.sectionConstantModel!.adminCommision!.isEnabled == true ? Constant.sectionConstantModel!.adminCommision!.amount.toString() : null; orderModel.couponCode = couponCodeTextEditController.value.text; @@ -501,7 +645,9 @@ class IntercityHomeController extends GetxController { orderModel.roundTrip = false; orderModel.sectionId = Constant.sectionConstantModel!.id; orderModel.createdAt = Timestamp.now(); - orderModel.otpCode = (maths.Random().nextInt(9000) + 1000).toString(); // Generate a 4-digit OTP + orderModel.otpCode = + (maths.Random().nextInt(9000) + 1000) + .toString(); // Generate a 4-digit OTP orderModel.status = Constant.orderPlaced; orderModel.scheduleDateTime = Timestamp.now(); log("Order Model : ${orderModel.toJson()}"); @@ -516,8 +662,10 @@ class IntercityHomeController extends GetxController { double getAmount(VehicleType vehicleType) { final double currentDistance = distance.value; - if (currentDistance <= (vehicleType.minimum_delivery_charges_within_km ?? 0)) { - return double.tryParse(vehicleType.minimum_delivery_charges.toString()) ?? 0.0; + if (currentDistance <= + (vehicleType.minimum_delivery_charges_within_km ?? 0)) { + return double.tryParse(vehicleType.minimum_delivery_charges.toString()) ?? + 0.0; } else { return (vehicleType.delivery_charges_per_km ?? 0.0) * currentDistance; } @@ -542,28 +690,50 @@ class IntercityHomeController extends GetxController { void setStopMarker(double lat, double lng, int index) { if (Constant.selectedMapType == 'osm') { // Add new stop marker without clearing - osmMarker.add(flutterMap.Marker(point: latlong.LatLng(lat, lng), width: 40, height: 40, child: stopIconOsm!)); + osmMarker.add( + flutterMap.Marker( + point: latlong.LatLng(lat, lng), + width: 40, + height: 40, + child: stopIconOsm!, + ), + ); getDirections(isStopMarker: true); } else { final markerId = MarkerId('Stop $index'); markers.removeWhere((marker) => marker.markerId == markerId); - markers.add(Marker(markerId: markerId, infoWindow: InfoWindow(title: 'Stop ${String.fromCharCode(index + 65)}'), position: LatLng(lat, lng), icon: stopIcon!)); + markers.add( + Marker( + markerId: markerId, + infoWindow: InfoWindow( + title: 'Stop ${String.fromCharCode(index + 65)}', + ), + position: LatLng(lat, lng), + icon: stopIcon!, + ), + ); getDirections(); } } void _setOsmMarker(double lat, double lng, {required bool isDeparture}) { - final marker = flutterMap.Marker(point: latlong.LatLng(lat, lng), width: 40, height: 40, child: isDeparture ? departureIconOsm! : destinationIconOsm!); + final marker = flutterMap.Marker( + point: latlong.LatLng(lat, lng), + width: 40, + height: 40, + child: isDeparture ? departureIconOsm! : destinationIconOsm!, + ); if (isDeparture) { departureLatLongOsm.value = latlong.LatLng(lat, lng); } else { destinationLatLongOsm.value = latlong.LatLng(lat, lng); } osmMarker.add(marker); - if (departureLatLongOsm.value.latitude != 0 && destinationLatLongOsm.value.latitude != 0) { + if (departureLatLongOsm.value.latitude != 0 && + destinationLatLongOsm.value.latitude != 0) { getDirections(); animateToSource(lat, lng); } @@ -585,14 +755,26 @@ class IntercityHomeController extends GetxController { markers.removeWhere((marker) => marker.markerId == markerId); // Add new marker - markers.add(Marker(markerId: markerId, position: pos, icon: icon, infoWindow: InfoWindow(title: title))); + markers.add( + Marker( + markerId: markerId, + position: pos, + icon: icon, + infoWindow: InfoWindow(title: title), + ), + ); mapController.animateCamera(CameraUpdate.newLatLngZoom(pos, 14)); - if (departureLatLong.value.latitude != 0 && destinationLatLong.value.latitude != 0) { + if (departureLatLong.value.latitude != 0 && + destinationLatLong.value.latitude != 0) { getDirections(); } else { - mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target: LatLng(lat, lng), zoom: 14))); + mapController.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition(target: LatLng(lat, lng), zoom: 14), + ), + ); } } @@ -601,25 +783,43 @@ class IntercityHomeController extends GetxController { final wayPoints = []; // Only add valid source - if (departureLatLongOsm.value.latitude != 0.0 && departureLatLongOsm.value.longitude != 0.0) { + if (departureLatLongOsm.value.latitude != 0.0 && + departureLatLongOsm.value.longitude != 0.0) { wayPoints.add(departureLatLongOsm.value); } // Only add valid destination - if (destinationLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.longitude != 0.0) { + if (destinationLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.longitude != 0.0) { wayPoints.add(destinationLatLongOsm.value); } if (!isStopMarker) osmMarker.clear(); // Add source marker - if (departureLatLongOsm.value.latitude != 0.0 && departureLatLongOsm.value.longitude != 0.0) { - osmMarker.add(flutterMap.Marker(point: departureLatLongOsm.value, width: 40, height: 40, child: departureIconOsm!)); + if (departureLatLongOsm.value.latitude != 0.0 && + departureLatLongOsm.value.longitude != 0.0) { + osmMarker.add( + flutterMap.Marker( + point: departureLatLongOsm.value, + width: 40, + height: 40, + child: departureIconOsm!, + ), + ); } // Add destination marker - if (destinationLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.longitude != 0.0) { - osmMarker.add(flutterMap.Marker(point: destinationLatLongOsm.value, width: 40, height: 40, child: destinationIconOsm!)); + if (destinationLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.longitude != 0.0) { + osmMarker.add( + flutterMap.Marker( + point: destinationLatLongOsm.value, + width: 40, + height: 40, + child: destinationIconOsm!, + ), + ); } if (wayPoints.length >= 2) { @@ -632,10 +832,14 @@ class IntercityHomeController extends GetxController { } Future fetchGoogleRouteWithWaypoints() async { - if (departureLatLong.value.latitude == 0.0 || destinationLatLong.value.latitude == 0.0) return; + if (departureLatLong.value.latitude == 0.0 || + destinationLatLong.value.latitude == 0.0) + return; - final origin = '${departureLatLong.value.latitude},${departureLatLong.value.longitude}'; - final destination = '${destinationLatLong.value.latitude},${destinationLatLong.value.longitude}'; + final origin = + '${departureLatLong.value.latitude},${departureLatLong.value.longitude}'; + final destination = + '${destinationLatLong.value.latitude},${destinationLatLong.value.longitude}'; final url = Uri.parse( 'https://maps.googleapis.com/maps/api/directions/json' @@ -654,7 +858,8 @@ class IntercityHomeController extends GetxController { // Polyline final encodedPolyline = route['overview_polyline']['points']; final decodedPoints = PolylinePoints.decodePolyline(encodedPolyline); - final coordinates = decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); + final coordinates = + decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); addPolyLine(coordinates); @@ -686,19 +891,26 @@ class IntercityHomeController extends GetxController { } Future fetchRouteWithWaypoints(List points) async { - final coordinates = points.map((p) => '${p.longitude},${p.latitude}').join(';'); - final url = Uri.parse('https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson'); + final coordinates = points + .map((p) => '${p.longitude},${p.latitude}') + .join(';'); + final url = Uri.parse( + 'https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson', + ); try { final response = await http.get(url); if (response.statusCode == 200) { final decoded = json.decode(response.body); - final geometry = decoded['routes'][0]['geometry']['coordinates'] as List; + final geometry = + decoded['routes'][0]['geometry']['coordinates'] as List; final dist = decoded['routes'][0]['distance']; final dur = decoded['routes'][0]['duration']; routePoints.clear(); - routePoints.addAll(geometry.map((coord) => latlong.LatLng(coord[1], coord[0]))); + routePoints.addAll( + geometry.map((coord) => latlong.LatLng(coord[1], coord[0])), + ); if (Constant.distanceType.toLowerCase() == "KM".toLowerCase()) { distance.value = dist / 1000.00; @@ -723,7 +935,10 @@ class IntercityHomeController extends GetxController { void zoomToPolylineOSM() { if (routePoints.isEmpty) return; // LatLngBounds requires at least two points - final bounds = flutterMap.LatLngBounds(routePoints.first, routePoints.first); + final bounds = flutterMap.LatLngBounds( + routePoints.first, + routePoints.first, + ); for (final point in routePoints) { bounds.extend(point); } @@ -735,8 +950,10 @@ class IntercityHomeController extends GetxController { double getBoundsZoomLevel(flutterMap.LatLngBounds bounds) { // Simple heuristic: zoom out for larger bounds - final latDiff = (bounds.northEast.latitude - bounds.southWest.latitude).abs(); - final lngDiff = (bounds.northEast.longitude - bounds.southWest.longitude).abs(); + final latDiff = + (bounds.northEast.latitude - bounds.southWest.latitude).abs(); + final lngDiff = + (bounds.northEast.longitude - bounds.southWest.longitude).abs(); double maxDiff = math.max(latDiff, lngDiff); if (maxDiff < 0.005) return 18.0; if (maxDiff < 0.01) return 16.0; @@ -748,7 +965,13 @@ class IntercityHomeController extends GetxController { void addPolyLine(List points) { final id = const PolylineId("poly"); - final polyline = Polyline(polylineId: id, color: AppThemeData.primary300, points: points, width: 6, geodesic: true); + final polyline = Polyline( + polylineId: id, + color: AppThemeData.primary300, + points: points, + width: 6, + geodesic: true, + ); polyLines[id] = polyline; if (points.length >= 2) { @@ -757,7 +980,10 @@ class IntercityHomeController extends GetxController { } } - Future updateCameraLocationToFitPolyline(List points, GoogleMapController? mapController) async { + Future updateCameraLocationToFitPolyline( + List points, + GoogleMapController? mapController, + ) async { if (mapController == null || points.isEmpty) return; double minLat = points.first.latitude, maxLat = points.first.latitude; double minLng = points.first.longitude, maxLng = points.first.longitude; @@ -767,16 +993,24 @@ class IntercityHomeController extends GetxController { if (p.longitude < minLng) minLng = p.longitude; if (p.longitude > maxLng) maxLng = p.longitude; } - final bounds = LatLngBounds(southwest: LatLng(minLat, minLng), northeast: LatLng(maxLat, maxLng)); + final bounds = LatLngBounds( + southwest: LatLng(minLat, minLng), + northeast: LatLng(maxLat, maxLng), + ); final cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 50); await checkCameraLocation(cameraUpdate, mapController); } Future animateToSource(double lat, double long) async { - final hasBothCoords = departureLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.latitude != 0.0; + final hasBothCoords = + departureLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.latitude != 0.0; if (hasBothCoords) { - await calculateZoomLevel(source: departureLatLongOsm.value, destination: destinationLatLongOsm.value); + await calculateZoomLevel( + source: departureLatLongOsm.value, + destination: destinationLatLongOsm.value, + ); } else { mapOsmController.move(latlong.LatLng(lat, long), 10); } @@ -784,15 +1018,25 @@ class IntercityHomeController extends GetxController { RxMap polyLines = {}.obs; - Future calculateZoomLevel({required latlong.LatLng source, required latlong.LatLng destination, double paddingFraction = 0.001}) async { + Future calculateZoomLevel({ + required latlong.LatLng source, + required latlong.LatLng destination, + double paddingFraction = 0.001, + }) async { final bounds = flutterMap.LatLngBounds.fromPoints([source, destination]); final screenSize = Size(Get.width, Get.height * 0.5); const double worldDimension = 256.0; const double maxZoom = 10.0; - double latToRad(double lat) => math.log((1 + math.sin(lat * math.pi / 180)) / (1 - math.sin(lat * math.pi / 180))) / 2; + double latToRad(double lat) => + math.log( + (1 + math.sin(lat * math.pi / 180)) / + (1 - math.sin(lat * math.pi / 180)), + ) / + 2; - double computeZoom(double screenPx, double worldPx, double fraction) => math.log(screenPx / worldPx / fraction) / math.ln2; + double computeZoom(double screenPx, double worldPx, double fraction) => + math.log(screenPx / worldPx / fraction) / math.ln2; final north = bounds.northEast.latitude; final south = bounds.southWest.latitude; @@ -810,27 +1054,48 @@ class IntercityHomeController extends GetxController { final latFraction = (latToRad(north) - latToRad(south)) / math.pi; final lngFraction = ((east - west + 360) % 360) / 360; - final latZoom = computeZoom(screenSize.height, worldDimension, latFraction + paddingFraction); - final lngZoom = computeZoom(screenSize.width, worldDimension, lngFraction + paddingFraction); + final latZoom = computeZoom( + screenSize.height, + worldDimension, + latFraction + paddingFraction, + ); + final lngZoom = computeZoom( + screenSize.width, + worldDimension, + lngFraction + paddingFraction, + ); final zoomLevel = math.min(latZoom, lngZoom).clamp(0.0, maxZoom); mapOsmController.move(center, zoomLevel); } } - Future updateCameraLocation(LatLng source, LatLng destination, GoogleMapController? mapController) async { + Future updateCameraLocation( + LatLng source, + LatLng destination, + GoogleMapController? mapController, + ) async { if (mapController == null) return; final bounds = LatLngBounds( - southwest: LatLng(math.min(source.latitude, destination.latitude), math.min(source.longitude, destination.longitude)), - northeast: LatLng(math.max(source.latitude, destination.latitude), math.max(source.longitude, destination.longitude)), + southwest: LatLng( + math.min(source.latitude, destination.latitude), + math.min(source.longitude, destination.longitude), + ), + northeast: LatLng( + math.max(source.latitude, destination.latitude), + math.max(source.longitude, destination.longitude), + ), ); final cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 90); await checkCameraLocation(cameraUpdate, mapController); } - Future checkCameraLocation(CameraUpdate cameraUpdate, GoogleMapController mapController) async { + Future checkCameraLocation( + CameraUpdate cameraUpdate, + GoogleMapController mapController, + ) async { await mapController.animateCamera(cameraUpdate); final l1 = await mapController.getVisibleRegion(); final l2 = await mapController.getVisibleRegion(); @@ -843,16 +1108,44 @@ class IntercityHomeController extends GetxController { Future setIcons() async { try { if (Constant.selectedMapType == 'osm') { - departureIconOsm = Image.asset("assets/icons/pickup.png", width: 30, height: 30); - destinationIconOsm = Image.asset("assets/icons/dropoff.png", width: 30, height: 30); - taxiIconOsm = Image.asset("assets/icons/ic_taxi.png", width: 30, height: 30); - stopIconOsm = Image.asset("assets/icons/location.png", width: 26, height: 26); + departureIconOsm = Image.asset( + "assets/icons/pickup.png", + width: 30, + height: 30, + ); + destinationIconOsm = Image.asset( + "assets/icons/dropoff.png", + width: 30, + height: 30, + ); + taxiIconOsm = Image.asset( + "assets/icons/ic_taxi.png", + width: 30, + height: 30, + ); + stopIconOsm = Image.asset( + "assets/icons/location.png", + width: 26, + height: 26, + ); } else { const config = ImageConfiguration(size: Size(48, 48)); - departureIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/pickup.png"); - destinationIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/dropoff.png"); - taxiIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/ic_taxi.png"); - stopIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/location.png"); + departureIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/pickup.png", + ); + destinationIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/dropoff.png", + ); + taxiIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/ic_taxi.png", + ); + stopIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/location.png", + ); } } catch (e) { print('Error loading icons: $e'); @@ -860,8 +1153,12 @@ class IntercityHomeController extends GetxController { } void clearMapDataIfLocationsRemoved() { - final isSourceEmpty = departureLatLongOsm.value.latitude == 0.0 && departureLatLongOsm.value.longitude == 0.0; - final isDestinationEmpty = destinationLatLongOsm.value.latitude == 0.0 && destinationLatLongOsm.value.longitude == 0.0; + final isSourceEmpty = + departureLatLongOsm.value.latitude == 0.0 && + departureLatLongOsm.value.longitude == 0.0; + final isDestinationEmpty = + destinationLatLongOsm.value.latitude == 0.0 && + destinationLatLongOsm.value.longitude == 0.0; if (isSourceEmpty || isDestinationEmpty) { // Clear polylines @@ -890,7 +1187,9 @@ class IntercityHomeController extends GetxController { // Remove marker if (Constant.selectedMapType == 'osm') { - osmMarker.removeWhere((marker) => marker.point == departureLatLongOsm.value); + osmMarker.removeWhere( + (marker) => marker.point == departureLatLongOsm.value, + ); } else { markers.removeWhere((marker) => marker.markerId.value == 'Departure'); } @@ -906,7 +1205,9 @@ class IntercityHomeController extends GetxController { destinationTextEditController.value.clear(); if (Constant.selectedMapType == 'osm') { - osmMarker.removeWhere((marker) => marker.point == destinationLatLongOsm.value); + osmMarker.removeWhere( + (marker) => marker.point == destinationLatLongOsm.value, + ); } else { markers.removeWhere((marker) => marker.markerId.value == 'Destination'); } @@ -916,9 +1217,16 @@ class IntercityHomeController extends GetxController { } Future searchPlaceNameOSM() async { - final url = Uri.parse('https://nominatim.openstreetmap.org/reverse?lat=${departureLatLongOsm.value.latitude}&lon=${departureLatLongOsm.value.longitude}&format=json'); + final url = Uri.parse( + 'https://nominatim.openstreetmap.org/reverse?lat=${departureLatLongOsm.value.latitude}&lon=${departureLatLongOsm.value.longitude}&format=json', + ); - final response = await http.get(url, headers: {'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)'}); + final response = await http.get( + url, + headers: { + 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', + }, + ); if (response.statusCode == 200) { log("response.body :: ${response.body}"); @@ -931,7 +1239,9 @@ class IntercityHomeController extends GetxController { final lat = departureLatLong.value.latitude; final lng = departureLatLong.value.longitude; - final url = Uri.parse('https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=${Constant.mapAPIKey}'); + final url = Uri.parse( + 'https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=${Constant.mapAPIKey}', + ); final response = await http.get(url); @@ -974,19 +1284,45 @@ class IntercityHomeController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -1028,20 +1364,32 @@ class IntercityHomeController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -1087,7 +1435,10 @@ class IntercityHomeController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -1097,8 +1448,14 @@ class IntercityHomeController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -1111,12 +1468,20 @@ class IntercityHomeController extends GetxController { }, ], "payer": {"email": userModel.value.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, "auto_return": "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -1174,9 +1539,12 @@ class IntercityHomeController extends GetxController { ///PayStack Payment Method Future payStackPayment(String totalAmount) async { - await PayStackURLGen.payStackURLGen(amount: (double.parse(totalAmount) * 100).toString(), currency: "ZAR", secretKey: payStackModel.value.secretKey.toString(), userModel: userModel.value).then(( - value, - ) async { + await PayStackURLGen.payStackURLGen( + amount: (double.parse(totalAmount) * 100).toString(), + currency: "ZAR", + secretKey: payStackModel.value.secretKey.toString(), + userModel: userModel.value, + ).then((value) async { if (value != null) { PayStackUrlModel payStackModel0 = value; Get.to( @@ -1196,15 +1564,23 @@ class IntercityHomeController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -1217,14 +1593,19 @@ class IntercityHomeController extends GetxController { "phonenumber": userModel.value.phoneNumber, // Add a real phone number "name": userModel.value.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1253,8 +1634,14 @@ class IntercityHomeController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: userModel.value).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: userModel.value, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -1293,7 +1680,14 @@ class IntercityHomeController extends GetxController { // }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -1329,24 +1723,38 @@ class IntercityHomeController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), "checksum_value": checkSum}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -1364,9 +1772,12 @@ class IntercityHomeController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -1384,7 +1795,10 @@ class IntercityHomeController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': userModel.value.phoneNumber, 'email': userModel.value.email}, + 'prefill': { + 'contact': userModel.value.phoneNumber, + 'email': userModel.value.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -1419,7 +1833,10 @@ class IntercityHomeController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -1437,15 +1854,30 @@ class IntercityHomeController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -1453,7 +1885,9 @@ class IntercityHomeController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -1470,13 +1904,30 @@ class IntercityHomeController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1488,13 +1939,22 @@ class IntercityHomeController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth!}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -1505,17 +1965,32 @@ class IntercityHomeController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; - String apiUrl = orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -1530,7 +2005,11 @@ class IntercityHomeController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -1544,7 +2023,9 @@ class IntercityHomeController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -1561,7 +2042,13 @@ class IntercityHomeController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1578,7 +2065,9 @@ class IntercityHomeController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -1591,7 +2080,11 @@ class IntercityHomeController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/address_list_controller.dart b/lib/controllers/address_list_controller.dart index 3a90915..ef1b6a2 100644 --- a/lib/controllers/address_list_controller.dart +++ b/lib/controllers/address_list_controller.dart @@ -1,6 +1,5 @@ import 'package:customer/models/user_model.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../constant/constant.dart'; import '../service/fire_store_utils.dart'; @@ -18,7 +17,9 @@ class AddressListController extends GetxController { } Future getUser() async { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { if (value != null) { userModel.value = value; if (userModel.value.shippingAddress != null) { diff --git a/lib/controllers/advertisement_list_controller.dart b/lib/controllers/advertisement_list_controller.dart index 56ae63b..a8f0e65 100644 --- a/lib/controllers/advertisement_list_controller.dart +++ b/lib/controllers/advertisement_list_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/models/advertisement_model.dart'; import 'package:customer/models/favourite_model.dart'; import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AdvertisementListController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/all_brand_product_controller.dart b/lib/controllers/all_brand_product_controller.dart index 5ffaec1..8a8867a 100644 --- a/lib/controllers/all_brand_product_controller.dart +++ b/lib/controllers/all_brand_product_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/models/brands_model.dart'; import 'package:customer/models/product_model.dart'; import 'package:customer/models/vendor_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AllBrandProductController extends GetxController { RxList productList = [].obs; @@ -27,19 +27,27 @@ class AllBrandProductController extends GetxController { } Future getProductByCategoryId() async { - List productDataList = await FireStoreUtils.getProductListByBrandId(brandModel.value.id.toString()); + List productDataList = + await FireStoreUtils.getProductListByBrandId( + brandModel.value.id.toString(), + ); List vendorList = await FireStoreUtils.getAllStoresFuture(); List allProduct = []; for (var vendor in vendorList) { await FireStoreUtils.getAllProducts(vendor.id.toString()).then((value) { - if (Constant.isSubscriptionModelApplied == true || vendor.adminCommission?.isEnabled == true) { - if (vendor.subscriptionPlan != null && Constant.isExpire(vendor) == false) { + if (Constant.isSubscriptionModelApplied == true || + vendor.adminCommission?.isEnabled == true) { + if (vendor.subscriptionPlan != null && + Constant.isExpire(vendor) == false) { if (vendor.subscriptionPlan?.itemLimit == '-1') { allProduct.addAll(value); } else { int selectedProduct = - value.length < int.parse(vendor.subscriptionPlan?.itemLimit ?? '0') ? (value.isEmpty ? 0 : (value.length)) : int.parse(vendor.subscriptionPlan?.itemLimit ?? '0'); + value.length < + int.parse(vendor.subscriptionPlan?.itemLimit ?? '0') + ? (value.isEmpty ? 0 : (value.length)) + : int.parse(vendor.subscriptionPlan?.itemLimit ?? '0'); allProduct.addAll(value.sublist(0, selectedProduct)); } } @@ -49,7 +57,9 @@ class AllBrandProductController extends GetxController { }); } for (var element in productDataList) { - final bool productIsInList = allProduct.any((product) => product.id == element.id); + final bool productIsInList = allProduct.any( + (product) => product.id == element.id, + ); if (productIsInList) { productList.add(element); } diff --git a/lib/controllers/all_category_product_controller.dart b/lib/controllers/all_category_product_controller.dart index d5454f6..d609ade 100644 --- a/lib/controllers/all_category_product_controller.dart +++ b/lib/controllers/all_category_product_controller.dart @@ -1,7 +1,7 @@ import 'package:customer/models/product_model.dart'; import 'package:customer/models/vendor_category_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AllCategoryProductController extends GetxController { RxBool isLoading = true.obs; @@ -25,6 +25,8 @@ class AllCategoryProductController extends GetxController { } Future getProductByCategoryId() async { - productList.value = await FireStoreUtils.getProductListByCategoryId(categoryModel.value.id.toString()); + productList.value = await FireStoreUtils.getProductListByCategoryId( + categoryModel.value.id.toString(), + ); } } diff --git a/lib/controllers/book_parcel_controller.dart b/lib/controllers/book_parcel_controller.dart index 825b239..e7d25e1 100644 --- a/lib/controllers/book_parcel_controller.dart +++ b/lib/controllers/book_parcel_controller.dart @@ -8,7 +8,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart' as latlong; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; @@ -23,26 +23,39 @@ import '../themes/show_toast_dialog.dart'; class BookParcelController extends GetxController { // Sender details - final Rx senderLocationController = TextEditingController().obs; - final Rx senderNameController = TextEditingController().obs; - final Rx senderMobileController = TextEditingController().obs; - final Rx senderWeightController = SingleValueDropDownController().obs; - final Rx senderNoteController = TextEditingController().obs; - final Rx senderCountryCodeController = TextEditingController(text: Constant.defaultCountryCode).obs; + final Rx senderLocationController = + TextEditingController().obs; + final Rx senderNameController = + TextEditingController().obs; + final Rx senderMobileController = + TextEditingController().obs; + final Rx senderWeightController = + SingleValueDropDownController().obs; + final Rx senderNoteController = + TextEditingController().obs; + final Rx senderCountryCodeController = + TextEditingController(text: Constant.defaultCountryCode).obs; // Receiver details - final Rx receiverLocationController = TextEditingController().obs; - final Rx receiverNameController = TextEditingController().obs; - final Rx receiverMobileController = TextEditingController().obs; - final Rx receiverNoteController = TextEditingController().obs; - final Rx receiverCountryCodeController = TextEditingController(text: Constant.defaultCountryCode).obs; + final Rx receiverLocationController = + TextEditingController().obs; + final Rx receiverNameController = + TextEditingController().obs; + final Rx receiverMobileController = + TextEditingController().obs; + final Rx receiverNoteController = + TextEditingController().obs; + final Rx receiverCountryCodeController = + TextEditingController(text: Constant.defaultCountryCode).obs; // Delivery type final RxString selectedDeliveryType = 'now'.obs; // Scheduled delivery fields - final Rx scheduledDateController = TextEditingController().obs; - final Rx scheduledTimeController = TextEditingController().obs; + final Rx scheduledDateController = + TextEditingController().obs; + final Rx scheduledTimeController = + TextEditingController().obs; final RxString scheduledDate = ''.obs; final RxString scheduledTime = ''.obs; @@ -83,7 +96,12 @@ class BookParcelController extends GetxController { } Future pickScheduledDate(BuildContext context) async { - final DateTime? picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365))); + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), + lastDate: DateTime.now().add(const Duration(days: 365)), + ); if (picked != null) { final formattedDate = "${picked.day}/${picked.month}/${picked.year}"; scheduledDate.value = formattedDate; @@ -92,7 +110,10 @@ class BookParcelController extends GetxController { } Future pickScheduledTime(BuildContext context) async { - final TimeOfDay? picked = await showTimePicker(context: context, initialTime: TimeOfDay.now()); + final TimeOfDay? picked = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ); if (picked != null) { final formattedTime = picked.format(context); scheduledTime.value = formattedTime; @@ -102,7 +123,10 @@ class BookParcelController extends GetxController { void onCameraClick(BuildContext context) { final action = CupertinoActionSheet( - message: Text('Add your parcel image.'.tr(), style: const TextStyle(fontSize: 15.0)), + message: Text( + 'Add your parcel image.'.tr(), + style: const TextStyle(fontSize: 15.0), + ), actions: [ CupertinoActionSheetAction( child: Text('Choose image from gallery'.tr()), @@ -118,14 +142,19 @@ class BookParcelController extends GetxController { child: Text('Take a picture'.tr()), onPressed: () async { Navigator.pop(context); - final XFile? photo = await _picker.pickImage(source: ImageSource.camera); + final XFile? photo = await _picker.pickImage( + source: ImageSource.camera, + ); if (photo != null) { images.add(photo); } }, ), ], - cancelButton: CupertinoActionSheetAction(child: Text('Cancel'.tr()), onPressed: () => Navigator.pop(context)), + cancelButton: CupertinoActionSheetAction( + child: Text('Cancel'.tr()), + onPressed: () => Navigator.pop(context), + ), ); showCupertinoModalPopup(context: context, builder: (context) => action); } @@ -134,11 +163,18 @@ class BookParcelController extends GetxController { try { await Geolocator.requestPermission(); final position = await Geolocator.getCurrentPosition(); - final placemarks = await placemarkFromCoordinates(position.latitude, position.longitude); + final placemarks = await placemarkFromCoordinates( + position.latitude, + position.longitude, + ); final place = placemarks.first; - final address = "${place.name}, ${place.subLocality}, ${place.locality}, ${place.administrativeArea}, ${place.postalCode}, ${place.country}"; + final address = + "${place.name}, ${place.subLocality}, ${place.locality}, ${place.administrativeArea}, ${place.postalCode}, ${place.country}"; - final userLocation = UserLocation(latitude: position.latitude, longitude: position.longitude); + final userLocation = UserLocation( + latitude: position.latitude, + longitude: position.longitude, + ); senderLocation.value = userLocation; senderLocationController.value.text = address; } catch (e) { @@ -179,7 +215,9 @@ class BookParcelController extends GetxController { ShowToastDialog.showToast("Please select parcel weight".tr()); return false; } else if (senderLocation.value == null || receiverLocation.value == null) { - ShowToastDialog.showToast("Please select both sender and receiver locations".tr()); + ShowToastDialog.showToast( + "Please select both sender and receiver locations".tr(), + ); return false; } return true; @@ -193,22 +231,37 @@ class BookParcelController extends GetxController { if (Constant.selectedMapType == 'osm') { print("Fetching route using OSM"); - print("Sender Location: ${senderLocation.value?.latitude}, ${senderLocation.value?.longitude}"); - print("Receiver Location: ${receiverLocation.value?.latitude}, ${receiverLocation.value?.longitude}"); + print( + "Sender Location: ${senderLocation.value?.latitude}, ${senderLocation.value?.longitude}", + ); + print( + "Receiver Location: ${receiverLocation.value?.latitude}, ${receiverLocation.value?.longitude}", + ); await fetchRouteWithWaypoints([ - latlong.LatLng(senderLocation.value?.latitude ?? 0.0, senderLocation.value?.longitude ?? 0.0), - latlong.LatLng(receiverLocation.value?.latitude ?? 0.0, receiverLocation.value?.longitude ?? 0.0), + latlong.LatLng( + senderLocation.value?.latitude ?? 0.0, + senderLocation.value?.longitude ?? 0.0, + ), + latlong.LatLng( + receiverLocation.value?.latitude ?? 0.0, + receiverLocation.value?.longitude ?? 0.0, + ), ]); } else { await fetchGoogleRouteWithWaypoints(); } if (distance.value < 0.5) { - ShowToastDialog.showToast("Sender's location to receiver's location should be more than 1 km.".tr()); + ShowToastDialog.showToast( + "Sender's location to receiver's location should be more than 1 km." + .tr(), + ); return; } - subTotal.value = (distance.value * double.parse(selectedWeight!.deliveryCharge.toString())); + subTotal.value = + (distance.value * + double.parse(selectedWeight!.deliveryCharge.toString())); goToCart(); } catch (e) { ShowToastDialog.showToast("Something went wrong while booking.".tr()); @@ -217,7 +270,10 @@ class BookParcelController extends GetxController { } void goToCart() { - DateTime senderPickup = isScheduled.value ? parseScheduledDateTime(scheduledDate.value, scheduledTime.value) : DateTime.now(); + DateTime senderPickup = + isScheduled.value + ? parseScheduledDateTime(scheduledDate.value, scheduledTime.value) + : DateTime.now(); print("Sender Pickup: $distance"); ParcelOrderModel order = ParcelOrderModel( @@ -236,22 +292,42 @@ class BookParcelController extends GetxController { taxSetting: Constant.taxList, isSchedule: isScheduled.value, sourcePoint: G( - geopoint: GeoPoint(senderLocation.value!.latitude ?? 0.0, senderLocation.value!.longitude ?? 0.0), - geohash: Geoflutterfire().point(latitude: senderLocation.value!.latitude ?? 0.0, longitude: senderLocation.value!.longitude ?? 0.0).hash, + geopoint: GeoPoint( + senderLocation.value!.latitude ?? 0.0, + senderLocation.value!.longitude ?? 0.0, + ), + geohash: + Geoflutterfire() + .point( + latitude: senderLocation.value!.latitude ?? 0.0, + longitude: senderLocation.value!.longitude ?? 0.0, + ) + .hash, ), destinationPoint: G( - geopoint: GeoPoint(receiverLocation.value!.latitude ?? 0.0, receiverLocation.value!.longitude ?? 0.0), - geohash: Geoflutterfire().point(latitude: receiverLocation.value!.latitude ?? 0.0, longitude: receiverLocation.value!.longitude ?? 0.0).hash, + geopoint: GeoPoint( + receiverLocation.value!.latitude ?? 0.0, + receiverLocation.value!.longitude ?? 0.0, + ), + geohash: + Geoflutterfire() + .point( + latitude: receiverLocation.value!.latitude ?? 0.0, + longitude: receiverLocation.value!.longitude ?? 0.0, + ) + .hash, ), sender: LocationInformation( address: senderLocationController.value.text, name: senderNameController.value.text, - phone: "(${senderCountryCodeController.value.text}) ${senderMobileController.value.text}", + phone: + "(${senderCountryCodeController.value.text}) ${senderMobileController.value.text}", ), receiver: LocationInformation( address: receiverLocationController.value.text, name: receiverNameController.value.text, - phone: "(${receiverCountryCodeController.value.text}) ${receiverMobileController.value.text}", + phone: + "(${receiverCountryCodeController.value.text}) ${receiverMobileController.value.text}", ), receiverLatLong: receiverLocation.value, senderLatLong: senderLocation.value, @@ -262,7 +338,10 @@ class BookParcelController extends GetxController { debugPrint("Subtotal: ${subTotal.value}"); debugPrint("Order JSON: ${order.toJson()}"); - Get.to(() => ParcelOrderConfirmationScreen(), arguments: {'parcelOrder': order, 'images': images}); + Get.to( + () => ParcelOrderConfirmationScreen(), + arguments: {'parcelOrder': order, 'images': images}, + ); } DateTime parseScheduledDateTime(String dateStr, String timeStr) { @@ -272,7 +351,10 @@ class BookParcelController extends GetxController { final month = int.parse(dateParts[1]); final year = int.parse(dateParts[2]); - final time = TimeOfDay(hour: int.parse(timeStr.split(':')[0]), minute: int.parse(timeStr.split(':')[1].split(' ')[0])); + final time = TimeOfDay( + hour: int.parse(timeStr.split(':')[0]), + minute: int.parse(timeStr.split(':')[1].split(' ')[0]), + ); final isPM = timeStr.toLowerCase().contains('pm'); final hour24 = isPM && time.hour < 12 ? time.hour + 12 : time.hour; @@ -284,9 +366,13 @@ class BookParcelController extends GetxController { } Future fetchGoogleRouteWithWaypoints() async { - final origin = '${senderLocation.value!.latitude},${senderLocation.value!.longitude}'; - final destination = '${receiverLocation.value!.latitude},${receiverLocation.value!.longitude}'; - final url = Uri.parse('https://maps.googleapis.com/maps/api/directions/json?origin=$origin&destination=$destination&mode=driving&key=${Constant.mapAPIKey}'); + final origin = + '${senderLocation.value!.latitude},${senderLocation.value!.longitude}'; + final destination = + '${receiverLocation.value!.latitude},${receiverLocation.value!.longitude}'; + final url = Uri.parse( + 'https://maps.googleapis.com/maps/api/directions/json?origin=$origin&destination=$destination&mode=driving&key=${Constant.mapAPIKey}', + ); try { final response = await http.get(url); @@ -315,8 +401,12 @@ class BookParcelController extends GetxController { } Future fetchRouteWithWaypoints(List points) async { - final coordinates = points.map((p) => '${p.longitude},${p.latitude}').join(';'); - final url = Uri.parse('https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson'); + final coordinates = points + .map((p) => '${p.longitude},${p.latitude}') + .join(';'); + final url = Uri.parse( + 'https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson', + ); try { final response = await http.get(url); diff --git a/lib/controllers/cab_booking_controller.dart b/lib/controllers/cab_booking_controller.dart index ce05319..ccd500c 100644 --- a/lib/controllers/cab_booking_controller.dart +++ b/lib/controllers/cab_booking_controller.dart @@ -46,7 +46,7 @@ import 'package:flutter_map/flutter_map.dart' as flutterMap; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_polyline_points/flutter_polyline_points.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; import 'package:latlong2/latlong.dart' as latlong; @@ -60,10 +60,13 @@ class CabBookingController extends GetxController { late GoogleMapController mapController; final flutterMap.MapController mapOsmController = flutterMap.MapController(); - final Rx sourceTextEditController = TextEditingController().obs; - final Rx destinationTextEditController = TextEditingController().obs; + final Rx sourceTextEditController = + TextEditingController().obs; + final Rx destinationTextEditController = + TextEditingController().obs; - final Rx couponCodeTextEditController = TextEditingController().obs; + final Rx couponCodeTextEditController = + TextEditingController().obs; final Rx currentLocation = Location().obs; @@ -133,64 +136,99 @@ class CabBookingController extends GetxController { await getPaymentSettings(); - FireStoreUtils.fireStore.collection(CollectionName.users).doc(FireStoreUtils.getCurrentUid()).snapshots().listen((userSnapshot) async { - if (!userSnapshot.exists) return; + FireStoreUtils.fireStore + .collection(CollectionName.users) + .doc(FireStoreUtils.getCurrentUid()) + .snapshots() + .listen((userSnapshot) async { + if (!userSnapshot.exists) return; - userModel.value = UserModel.fromJson(userSnapshot.data()!); + userModel.value = UserModel.fromJson(userSnapshot.data()!); - if (userModel.value.inProgressOrderID != null && userModel.value.inProgressOrderID!.isNotEmpty) { - String? validRideId; + if (userModel.value.inProgressOrderID != null && + userModel.value.inProgressOrderID!.isNotEmpty) { + String? validRideId; - for (String id in userModel.value.inProgressOrderID!) { - final rideDoc = await FireStoreUtils.fireStore.collection(CollectionName.rides).doc(id).get(); + for (String id in userModel.value.inProgressOrderID!) { + final rideDoc = + await FireStoreUtils.fireStore + .collection(CollectionName.rides) + .doc(id) + .get(); - if (rideDoc.exists && (rideDoc.data()?['rideType'] ?? '').toString().toLowerCase() == "ride") { - validRideId = userModel.value.inProgressOrderID!.first!; - break; - } - } - - FireStoreUtils.fireStore.collection(CollectionName.rides).doc(validRideId).snapshots().listen((rideSnapshot) async { - if (!rideSnapshot.exists) return; - - final rideData = rideSnapshot.data()!; - currentOrder.value = CabOrderModel.fromJson(rideData); - final status = currentOrder.value.status; - - if (status == Constant.driverAccepted || status == Constant.orderInTransit) { - FireStoreUtils.fireStore.collection(CollectionName.users).doc(currentOrder.value.driverId).snapshots().listen((event) async { - if (event.exists && event.data() != null) { - UserModel driverModel0 = UserModel.fromJson(event.data()!); - driverModel.value = driverModel0; - await updateDriverRoute(driverModel0); + if (rideDoc.exists && + (rideDoc.data()?['rideType'] ?? '') + .toString() + .toLowerCase() == + "ride") { + validRideId = userModel.value.inProgressOrderID!.first!; + break; } - }); - } + } - print("Current Ride Status: $status"); - if (status == Constant.orderPlaced || status == Constant.driverPending || status == Constant.driverRejected || (status == Constant.orderAccepted && currentOrder.value.driverId == null)) { - bottomSheetType.value = 'waitingForDriver'; - } else if (status == Constant.driverAccepted || status == Constant.orderInTransit) { - bottomSheetType.value = 'driverDetails'; - sourceTextEditController.value.text = currentOrder.value.sourceLocationName ?? ''; - destinationTextEditController.value.text = currentOrder.value.destinationLocationName ?? ''; - selectedPaymentMethod.value = currentOrder.value.paymentMethod ?? ''; - calculateTotalAmountAfterAccept(); - } else if (status == Constant.orderCompleted) { - userModel.value.inProgressOrderID!.remove(validRideId); - await FireStoreUtils.updateUser(userModel.value); + FireStoreUtils.fireStore + .collection(CollectionName.rides) + .doc(validRideId) + .snapshots() + .listen((rideSnapshot) async { + if (!rideSnapshot.exists) return; + + final rideData = rideSnapshot.data()!; + currentOrder.value = CabOrderModel.fromJson(rideData); + final status = currentOrder.value.status; + + if (status == Constant.driverAccepted || + status == Constant.orderInTransit) { + FireStoreUtils.fireStore + .collection(CollectionName.users) + .doc(currentOrder.value.driverId) + .snapshots() + .listen((event) async { + if (event.exists && event.data() != null) { + UserModel driverModel0 = UserModel.fromJson( + event.data()!, + ); + driverModel.value = driverModel0; + await updateDriverRoute(driverModel0); + } + }); + } + + print("Current Ride Status: $status"); + if (status == Constant.orderPlaced || + status == Constant.driverPending || + status == Constant.driverRejected || + (status == Constant.orderAccepted && + currentOrder.value.driverId == null)) { + bottomSheetType.value = 'waitingForDriver'; + } else if (status == Constant.driverAccepted || + status == Constant.orderInTransit) { + bottomSheetType.value = 'driverDetails'; + sourceTextEditController.value.text = + currentOrder.value.sourceLocationName ?? ''; + destinationTextEditController.value.text = + currentOrder.value.destinationLocationName ?? ''; + selectedPaymentMethod.value = + currentOrder.value.paymentMethod ?? ''; + calculateTotalAmountAfterAccept(); + } else if (status == Constant.orderCompleted) { + userModel.value.inProgressOrderID!.remove(validRideId); + await FireStoreUtils.updateUser(userModel.value); + bottomSheetType.value = 'location'; + Get.back(); + } + }); + } else { bottomSheetType.value = 'location'; - Get.back(); + if (Constant.currentLocation != null) { + setDepartureMarker( + Constant.currentLocation!.latitude, + Constant.currentLocation!.longitude, + ); + searchPlaceNameOSM(); + } } }); - } else { - bottomSheetType.value = 'location'; - if (Constant.currentLocation != null) { - setDepartureMarker(Constant.currentLocation!.latitude, Constant.currentLocation!.longitude); - searchPlaceNameOSM(); - } - } - }); final coupons = await FireStoreUtils.getCabCoupon(); cabCouponList.value = coupons; @@ -217,18 +255,30 @@ class CabBookingController extends GetxController { if (order.status == Constant.driverAccepted) { // DRIVER → PICKUP - await fetchRouteWithWaypoints([latlong.LatLng(driverLat, driverLng), latlong.LatLng(pickupLat, pickupLng)]); + await fetchRouteWithWaypoints([ + latlong.LatLng(driverLat, driverLng), + latlong.LatLng(pickupLat, pickupLng), + ]); } else if (order.status == Constant.orderInTransit) { // PICKUP → DESTINATION - await fetchRouteWithWaypoints([latlong.LatLng(driverLat, driverLng), latlong.LatLng(destLat, destLng)]); + await fetchRouteWithWaypoints([ + latlong.LatLng(driverLat, driverLng), + latlong.LatLng(destLat, destLng), + ]); } updateRouteMarkers(driverModel); } else { /// For Google Maps if (order.status == Constant.driverAccepted) { - await fetchGoogleRouteBetween(LatLng(driverLat, driverLng), LatLng(pickupLat, pickupLng)); + await fetchGoogleRouteBetween( + LatLng(driverLat, driverLng), + LatLng(pickupLat, pickupLng), + ); } else if (order.status == Constant.orderInTransit) { - await fetchGoogleRouteBetween(LatLng(driverLat, driverLng), LatLng(destLat, destLng)); + await fetchGoogleRouteBetween( + LatLng(driverLat, driverLng), + LatLng(destLat, destLng), + ); } updateRouteMarkers(driverModel); } @@ -252,12 +302,24 @@ class CabBookingController extends GetxController { markers.clear(); osmMarker.clear(); - final departureBytes = await Constant().getBytesFromAsset('assets/images/location_black3x.png', 50); - final destinationBytes = await Constant().getBytesFromAsset('assets/images/location_orange3x.png', 50); + final departureBytes = await Constant().getBytesFromAsset( + 'assets/images/location_black3x.png', + 50, + ); + final destinationBytes = await Constant().getBytesFromAsset( + 'assets/images/location_orange3x.png', + 50, + ); final driverBytesRaw = (Constant.sectionConstantModel?.markerIcon?.isNotEmpty ?? false) - ? await Constant().getBytesFromUrl(Constant.sectionConstantModel!.markerIcon!, width: 120) - : await Constant().getBytesFromAsset('assets/images/ic_cab.png', 50); + ? await Constant().getBytesFromUrl( + Constant.sectionConstantModel!.markerIcon!, + width: 120, + ) + : await Constant().getBytesFromAsset( + 'assets/images/ic_cab.png', + 50, + ); departureIcon = BitmapDescriptor.fromBytes(departureBytes); destinationIcon = BitmapDescriptor.fromBytes(destinationBytes); @@ -266,7 +328,15 @@ class CabBookingController extends GetxController { if (Constant.selectedMapType == 'osm') { if (order.status == Constant.driverAccepted) { osmMarker.addAll([ - flutterMap.Marker(point: latlong.LatLng(pickupLat, pickupLng), width: 40, height: 40, child: Image.asset('assets/images/location_black3x.png', width: 40)), + flutterMap.Marker( + point: latlong.LatLng(pickupLat, pickupLng), + width: 40, + height: 40, + child: Image.asset( + 'assets/images/location_black3x.png', + width: 40, + ), + ), flutterMap.Marker( point: latlong.LatLng(driverLat, driverLng), width: 45, @@ -277,13 +347,26 @@ class CabBookingController extends GetxController { height: 50, imageUrl: Constant.sectionConstantModel!.markerIcon.toString(), placeholder: (context, url) => Constant.loader(), - errorWidget: (context, url, error) => SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 2)), + errorWidget: + (context, url, error) => SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator(strokeWidth: 2), + ), ), ), ]); } else if (order.status == Constant.orderInTransit) { osmMarker.addAll([ - flutterMap.Marker(point: latlong.LatLng(destLat, destLng), width: 40, height: 40, child: Image.asset('assets/images/location_orange3x.png', width: 40)), + flutterMap.Marker( + point: latlong.LatLng(destLat, destLng), + width: 40, + height: 40, + child: Image.asset( + 'assets/images/location_orange3x.png', + width: 40, + ), + ), flutterMap.Marker( point: latlong.LatLng(driverLat, driverLng), width: 45, @@ -294,7 +377,12 @@ class CabBookingController extends GetxController { height: 50, imageUrl: Constant.sectionConstantModel!.markerIcon.toString(), placeholder: (context, url) => Constant.loader(), - errorWidget: (context, url, error) => SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 2)), + errorWidget: + (context, url, error) => SizedBox( + width: 30, + height: 30, + child: CircularProgressIndicator(strokeWidth: 2), + ), ), ), ]); @@ -306,9 +394,18 @@ class CabBookingController extends GetxController { markerId: const MarkerId("pickup"), position: LatLng(pickupLat, pickupLng), infoWindow: InfoWindow(title: "Pickup Location".tr()), - icon: departureIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen), + icon: + departureIcon ?? + BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueGreen, + ), + ), + Marker( + markerId: const MarkerId("driver"), + position: LatLng(driverLat, driverLng), + infoWindow: InfoWindow(title: "Driver at Pickup".tr()), + icon: taxiIcon ?? BitmapDescriptor.defaultMarker, ), - Marker(markerId: const MarkerId("driver"), position: LatLng(driverLat, driverLng), infoWindow: InfoWindow(title: "Driver at Pickup".tr()), icon: taxiIcon ?? BitmapDescriptor.defaultMarker), ]); } else if (order.status == Constant.orderInTransit) { markers.addAll([ @@ -316,9 +413,18 @@ class CabBookingController extends GetxController { markerId: const MarkerId("destination"), position: LatLng(destLat, destLng), infoWindow: InfoWindow(title: "Destination Location".tr()), - icon: destinationIcon ?? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed), + icon: + destinationIcon ?? + BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueRed, + ), + ), + Marker( + markerId: const MarkerId("driver"), + position: LatLng(driverLat, driverLng), + infoWindow: InfoWindow(title: "Driver Location".tr()), + icon: taxiIcon ?? BitmapDescriptor.defaultMarker, ), - Marker(markerId: const MarkerId("driver"), position: LatLng(driverLat, driverLng), infoWindow: InfoWindow(title: "Driver Location".tr()), icon: taxiIcon ?? BitmapDescriptor.defaultMarker), ]); } } @@ -329,7 +435,10 @@ class CabBookingController extends GetxController { } } - Future fetchGoogleRouteBetween(LatLng originPoint, LatLng destPoint) async { + Future fetchGoogleRouteBetween( + LatLng originPoint, + LatLng destPoint, + ) async { final origin = '${originPoint.latitude},${originPoint.longitude}'; final destination = '${destPoint.latitude},${destPoint.longitude}'; final url = Uri.parse( @@ -346,7 +455,8 @@ class CabBookingController extends GetxController { final route = data['routes'][0]; final encodedPolyline = route['overview_polyline']['points']; final decodedPoints = PolylinePoints.decodePolyline(encodedPolyline); - final coordinates = decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); + final coordinates = + decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); addPolyLine(coordinates); @@ -373,7 +483,12 @@ class CabBookingController extends GetxController { if (currentOrder.value.taxSetting != null) { for (var element in currentOrder.value.taxSetting!) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } } @@ -389,11 +504,19 @@ class CabBookingController extends GetxController { subTotal.value = getAmount(selectedVehicleType.value); if (selectedCouponModel.value.id != null) { - discount.value = Constant.calculateDiscount(amount: subTotal.value.toString(), offerModel: selectedCouponModel.value); + discount.value = Constant.calculateDiscount( + amount: subTotal.value.toString(), + offerModel: selectedCouponModel.value, + ); } for (var element in Constant.taxList) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } totalAmount.value = (subTotal.value - discount.value) + taxAmount.value; @@ -430,9 +553,14 @@ class CabBookingController extends GetxController { serviceType: Constant.parcelServiceType, ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ); } }); } @@ -446,13 +574,25 @@ class CabBookingController extends GetxController { Future placeOrder() async { DestinationLocation sourceLocation = DestinationLocation( - latitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.latitude : departureLatLong.value.latitude, - longitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.longitude : departureLatLong.value.longitude, + latitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.latitude + : departureLatLong.value.latitude, + longitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.longitude + : departureLatLong.value.longitude, ); DestinationLocation destinationLocation = DestinationLocation( - latitude: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value.latitude : destinationLatLong.value.latitude, - longitude: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value.longitude : destinationLatLong.value.longitude, + latitude: + Constant.selectedMapType == 'osm' + ? destinationLatLongOsm.value.latitude + : destinationLatLong.value.latitude, + longitude: + Constant.selectedMapType == 'osm' + ? destinationLatLongOsm.value.longitude + : destinationLatLong.value.longitude, ); CabOrderModel orderModel = CabOrderModel(); @@ -463,7 +603,8 @@ class CabBookingController extends GetxController { orderModel.vehicleType = selectedVehicleType.value; orderModel.authorID = FireStoreUtils.getCurrentUid(); orderModel.sourceLocationName = sourceTextEditController.value.text; - orderModel.destinationLocationName = destinationTextEditController.value.text; + orderModel.destinationLocationName = + destinationTextEditController.value.text; orderModel.sourceLocation = sourceLocation; orderModel.destinationLocation = destinationLocation; @@ -475,11 +616,14 @@ class CabBookingController extends GetxController { orderModel.taxSetting = Constant.taxList; orderModel.adminCommissionType = - Constant.sectionConstantModel!.adminCommision != null && Constant.sectionConstantModel!.adminCommision!.isEnabled == true - ? Constant.sectionConstantModel!.adminCommision!.commissionType.toString() + Constant.sectionConstantModel!.adminCommision != null && + Constant.sectionConstantModel!.adminCommision!.isEnabled == true + ? Constant.sectionConstantModel!.adminCommision!.commissionType + .toString() : null; orderModel.adminCommission = - Constant.sectionConstantModel!.adminCommision != null && Constant.sectionConstantModel!.adminCommision!.isEnabled == true + Constant.sectionConstantModel!.adminCommision != null && + Constant.sectionConstantModel!.adminCommision!.isEnabled == true ? Constant.sectionConstantModel!.adminCommision!.amount.toString() : null; orderModel.couponCode = couponCodeTextEditController.value.text; @@ -492,7 +636,9 @@ class CabBookingController extends GetxController { orderModel.roundTrip = false; orderModel.sectionId = Constant.sectionConstantModel!.id; orderModel.createdAt = Timestamp.now(); - orderModel.otpCode = (maths.Random().nextInt(9000) + 1000).toString(); // Generate a 4-digit OTP + orderModel.otpCode = + (maths.Random().nextInt(9000) + 1000) + .toString(); // Generate a 4-digit OTP orderModel.status = Constant.orderPlaced; orderModel.scheduleDateTime = Timestamp.now(); log("Order Model : ${orderModel.toJson()}"); @@ -507,8 +653,10 @@ class CabBookingController extends GetxController { double getAmount(VehicleType vehicleType) { final double currentDistance = distance.value; - if (currentDistance <= (vehicleType.minimum_delivery_charges_within_km ?? 0)) { - return double.tryParse(vehicleType.minimum_delivery_charges.toString()) ?? 0.0; + if (currentDistance <= + (vehicleType.minimum_delivery_charges_within_km ?? 0)) { + return double.tryParse(vehicleType.minimum_delivery_charges.toString()) ?? + 0.0; } else { return (vehicleType.delivery_charges_per_km ?? 0.0) * currentDistance; } @@ -533,28 +681,50 @@ class CabBookingController extends GetxController { void setStopMarker(double lat, double lng, int index) { if (Constant.selectedMapType == 'osm') { // Add new stop marker without clearing - osmMarker.add(flutterMap.Marker(point: latlong.LatLng(lat, lng), width: 40, height: 40, child: stopIconOsm!)); + osmMarker.add( + flutterMap.Marker( + point: latlong.LatLng(lat, lng), + width: 40, + height: 40, + child: stopIconOsm!, + ), + ); getDirections(isStopMarker: true); } else { final markerId = MarkerId('Stop $index'); markers.removeWhere((marker) => marker.markerId == markerId); - markers.add(Marker(markerId: markerId, infoWindow: InfoWindow(title: '${'Stop'.tr()} ${String.fromCharCode(index + 65)}'), position: LatLng(lat, lng), icon: stopIcon!)); + markers.add( + Marker( + markerId: markerId, + infoWindow: InfoWindow( + title: '${'Stop'.tr()} ${String.fromCharCode(index + 65)}', + ), + position: LatLng(lat, lng), + icon: stopIcon!, + ), + ); getDirections(); } } void _setOsmMarker(double lat, double lng, {required bool isDeparture}) { - final marker = flutterMap.Marker(point: latlong.LatLng(lat, lng), width: 40, height: 40, child: isDeparture ? departureIconOsm! : destinationIconOsm!); + final marker = flutterMap.Marker( + point: latlong.LatLng(lat, lng), + width: 40, + height: 40, + child: isDeparture ? departureIconOsm! : destinationIconOsm!, + ); if (isDeparture) { departureLatLongOsm.value = latlong.LatLng(lat, lng); } else { destinationLatLongOsm.value = latlong.LatLng(lat, lng); } osmMarker.add(marker); - if (departureLatLongOsm.value.latitude != 0 && destinationLatLongOsm.value.latitude != 0) { + if (departureLatLongOsm.value.latitude != 0 && + destinationLatLongOsm.value.latitude != 0) { getDirections(); animateToSource(lat, lng); } @@ -576,14 +746,26 @@ class CabBookingController extends GetxController { markers.removeWhere((marker) => marker.markerId == markerId); // Add new marker - markers.add(Marker(markerId: markerId, position: pos, icon: icon, infoWindow: InfoWindow(title: title))); + markers.add( + Marker( + markerId: markerId, + position: pos, + icon: icon, + infoWindow: InfoWindow(title: title), + ), + ); mapController.animateCamera(CameraUpdate.newLatLngZoom(pos, 14)); - if (departureLatLong.value.latitude != 0 && destinationLatLong.value.latitude != 0) { + if (departureLatLong.value.latitude != 0 && + destinationLatLong.value.latitude != 0) { getDirections(); } else { - mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target: LatLng(lat, lng), zoom: 14))); + mapController.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition(target: LatLng(lat, lng), zoom: 14), + ), + ); } } @@ -592,25 +774,43 @@ class CabBookingController extends GetxController { final wayPoints = []; // Only add valid source - if (departureLatLongOsm.value.latitude != 0.0 && departureLatLongOsm.value.longitude != 0.0) { + if (departureLatLongOsm.value.latitude != 0.0 && + departureLatLongOsm.value.longitude != 0.0) { wayPoints.add(departureLatLongOsm.value); } // Only add valid destination - if (destinationLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.longitude != 0.0) { + if (destinationLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.longitude != 0.0) { wayPoints.add(destinationLatLongOsm.value); } if (!isStopMarker) osmMarker.clear(); // Add source marker - if (departureLatLongOsm.value.latitude != 0.0 && departureLatLongOsm.value.longitude != 0.0) { - osmMarker.add(flutterMap.Marker(point: departureLatLongOsm.value, width: 40, height: 40, child: departureIconOsm!)); + if (departureLatLongOsm.value.latitude != 0.0 && + departureLatLongOsm.value.longitude != 0.0) { + osmMarker.add( + flutterMap.Marker( + point: departureLatLongOsm.value, + width: 40, + height: 40, + child: departureIconOsm!, + ), + ); } // Add destination marker - if (destinationLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.longitude != 0.0) { - osmMarker.add(flutterMap.Marker(point: destinationLatLongOsm.value, width: 40, height: 40, child: destinationIconOsm!)); + if (destinationLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.longitude != 0.0) { + osmMarker.add( + flutterMap.Marker( + point: destinationLatLongOsm.value, + width: 40, + height: 40, + child: destinationIconOsm!, + ), + ); } if (wayPoints.length >= 2) { @@ -623,10 +823,14 @@ class CabBookingController extends GetxController { } Future fetchGoogleRouteWithWaypoints() async { - if (departureLatLong.value.latitude == 0.0 || destinationLatLong.value.latitude == 0.0) return; + if (departureLatLong.value.latitude == 0.0 || + destinationLatLong.value.latitude == 0.0) + return; - final origin = '${departureLatLong.value.latitude},${departureLatLong.value.longitude}'; - final destination = '${destinationLatLong.value.latitude},${destinationLatLong.value.longitude}'; + final origin = + '${departureLatLong.value.latitude},${departureLatLong.value.longitude}'; + final destination = + '${destinationLatLong.value.latitude},${destinationLatLong.value.longitude}'; final url = Uri.parse( 'https://maps.googleapis.com/maps/api/directions/json' @@ -645,7 +849,8 @@ class CabBookingController extends GetxController { // Polyline final encodedPolyline = route['overview_polyline']['points']; final decodedPoints = PolylinePoints.decodePolyline(encodedPolyline); - final coordinates = decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); + final coordinates = + decodedPoints.map((e) => LatLng(e.latitude, e.longitude)).toList(); addPolyLine(coordinates); @@ -677,19 +882,26 @@ class CabBookingController extends GetxController { } Future fetchRouteWithWaypoints(List points) async { - final coordinates = points.map((p) => '${p.longitude},${p.latitude}').join(';'); - final url = Uri.parse('https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson'); + final coordinates = points + .map((p) => '${p.longitude},${p.latitude}') + .join(';'); + final url = Uri.parse( + 'https://router.project-osrm.org/route/v1/driving/$coordinates?overview=full&geometries=geojson', + ); try { final response = await http.get(url); if (response.statusCode == 200) { final decoded = json.decode(response.body); - final geometry = decoded['routes'][0]['geometry']['coordinates'] as List; + final geometry = + decoded['routes'][0]['geometry']['coordinates'] as List; final dist = decoded['routes'][0]['distance']; final dur = decoded['routes'][0]['duration']; routePoints.clear(); - routePoints.addAll(geometry.map((coord) => latlong.LatLng(coord[1], coord[0]))); + routePoints.addAll( + geometry.map((coord) => latlong.LatLng(coord[1], coord[0])), + ); if (Constant.distanceType.toLowerCase() == "KM".toLowerCase()) { distance.value = dist / 1000.00; @@ -714,7 +926,10 @@ class CabBookingController extends GetxController { void zoomToPolylineOSM() { if (routePoints.isEmpty) return; // LatLngBounds requires at least two points - final bounds = flutterMap.LatLngBounds(routePoints.first, routePoints.first); + final bounds = flutterMap.LatLngBounds( + routePoints.first, + routePoints.first, + ); for (final point in routePoints) { bounds.extend(point); } @@ -726,8 +941,10 @@ class CabBookingController extends GetxController { double getBoundsZoomLevel(flutterMap.LatLngBounds bounds) { // Simple heuristic: zoom out for larger bounds - final latDiff = (bounds.northEast.latitude - bounds.southWest.latitude).abs(); - final lngDiff = (bounds.northEast.longitude - bounds.southWest.longitude).abs(); + final latDiff = + (bounds.northEast.latitude - bounds.southWest.latitude).abs(); + final lngDiff = + (bounds.northEast.longitude - bounds.southWest.longitude).abs(); double maxDiff = math.max(latDiff, lngDiff); if (maxDiff < 0.005) return 18.0; if (maxDiff < 0.01) return 16.0; @@ -739,7 +956,13 @@ class CabBookingController extends GetxController { void addPolyLine(List points) { final id = const PolylineId("poly"); - final polyline = Polyline(polylineId: id, color: AppThemeData.primary300, points: points, width: 6, geodesic: true); + final polyline = Polyline( + polylineId: id, + color: AppThemeData.primary300, + points: points, + width: 6, + geodesic: true, + ); polyLines[id] = polyline; if (points.length >= 2) { @@ -748,7 +971,10 @@ class CabBookingController extends GetxController { } } - Future updateCameraLocationToFitPolyline(List points, GoogleMapController? mapController) async { + Future updateCameraLocationToFitPolyline( + List points, + GoogleMapController? mapController, + ) async { if (mapController == null || points.isEmpty) return; double minLat = points.first.latitude, maxLat = points.first.latitude; double minLng = points.first.longitude, maxLng = points.first.longitude; @@ -758,16 +984,24 @@ class CabBookingController extends GetxController { if (p.longitude < minLng) minLng = p.longitude; if (p.longitude > maxLng) maxLng = p.longitude; } - final bounds = LatLngBounds(southwest: LatLng(minLat, minLng), northeast: LatLng(maxLat, maxLng)); + final bounds = LatLngBounds( + southwest: LatLng(minLat, minLng), + northeast: LatLng(maxLat, maxLng), + ); final cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 50); await checkCameraLocation(cameraUpdate, mapController); } Future animateToSource(double lat, double long) async { - final hasBothCoords = departureLatLongOsm.value.latitude != 0.0 && destinationLatLongOsm.value.latitude != 0.0; + final hasBothCoords = + departureLatLongOsm.value.latitude != 0.0 && + destinationLatLongOsm.value.latitude != 0.0; if (hasBothCoords) { - await calculateZoomLevel(source: departureLatLongOsm.value, destination: destinationLatLongOsm.value); + await calculateZoomLevel( + source: departureLatLongOsm.value, + destination: destinationLatLongOsm.value, + ); } else { mapOsmController.move(latlong.LatLng(lat, long), 10); } @@ -775,15 +1009,25 @@ class CabBookingController extends GetxController { RxMap polyLines = {}.obs; - Future calculateZoomLevel({required latlong.LatLng source, required latlong.LatLng destination, double paddingFraction = 0.001}) async { + Future calculateZoomLevel({ + required latlong.LatLng source, + required latlong.LatLng destination, + double paddingFraction = 0.001, + }) async { final bounds = flutterMap.LatLngBounds.fromPoints([source, destination]); final screenSize = Size(Get.width, Get.height * 0.5); const double worldDimension = 256.0; const double maxZoom = 10.0; - double latToRad(double lat) => math.log((1 + math.sin(lat * math.pi / 180)) / (1 - math.sin(lat * math.pi / 180))) / 2; + double latToRad(double lat) => + math.log( + (1 + math.sin(lat * math.pi / 180)) / + (1 - math.sin(lat * math.pi / 180)), + ) / + 2; - double computeZoom(double screenPx, double worldPx, double fraction) => math.log(screenPx / worldPx / fraction) / math.ln2; + double computeZoom(double screenPx, double worldPx, double fraction) => + math.log(screenPx / worldPx / fraction) / math.ln2; final north = bounds.northEast.latitude; final south = bounds.southWest.latitude; @@ -801,27 +1045,48 @@ class CabBookingController extends GetxController { final latFraction = (latToRad(north) - latToRad(south)) / math.pi; final lngFraction = ((east - west + 360) % 360) / 360; - final latZoom = computeZoom(screenSize.height, worldDimension, latFraction + paddingFraction); - final lngZoom = computeZoom(screenSize.width, worldDimension, lngFraction + paddingFraction); + final latZoom = computeZoom( + screenSize.height, + worldDimension, + latFraction + paddingFraction, + ); + final lngZoom = computeZoom( + screenSize.width, + worldDimension, + lngFraction + paddingFraction, + ); final zoomLevel = math.min(latZoom, lngZoom).clamp(0.0, maxZoom); mapOsmController.move(center, zoomLevel); } } - Future updateCameraLocation(LatLng source, LatLng destination, GoogleMapController? mapController) async { + Future updateCameraLocation( + LatLng source, + LatLng destination, + GoogleMapController? mapController, + ) async { if (mapController == null) return; final bounds = LatLngBounds( - southwest: LatLng(math.min(source.latitude, destination.latitude), math.min(source.longitude, destination.longitude)), - northeast: LatLng(math.max(source.latitude, destination.latitude), math.max(source.longitude, destination.longitude)), + southwest: LatLng( + math.min(source.latitude, destination.latitude), + math.min(source.longitude, destination.longitude), + ), + northeast: LatLng( + math.max(source.latitude, destination.latitude), + math.max(source.longitude, destination.longitude), + ), ); final cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 90); await checkCameraLocation(cameraUpdate, mapController); } - Future checkCameraLocation(CameraUpdate cameraUpdate, GoogleMapController mapController) async { + Future checkCameraLocation( + CameraUpdate cameraUpdate, + GoogleMapController mapController, + ) async { await mapController.animateCamera(cameraUpdate); final l1 = await mapController.getVisibleRegion(); final l2 = await mapController.getVisibleRegion(); @@ -834,16 +1099,44 @@ class CabBookingController extends GetxController { Future setIcons() async { try { if (Constant.selectedMapType == 'osm') { - departureIconOsm = Image.asset("assets/icons/pickup.png", width: 30, height: 30); - destinationIconOsm = Image.asset("assets/icons/dropoff.png", width: 30, height: 30); - taxiIconOsm = Image.asset("assets/icons/ic_taxi.png", width: 30, height: 30); - stopIconOsm = Image.asset("assets/icons/location.png", width: 26, height: 26); + departureIconOsm = Image.asset( + "assets/icons/pickup.png", + width: 30, + height: 30, + ); + destinationIconOsm = Image.asset( + "assets/icons/dropoff.png", + width: 30, + height: 30, + ); + taxiIconOsm = Image.asset( + "assets/icons/ic_taxi.png", + width: 30, + height: 30, + ); + stopIconOsm = Image.asset( + "assets/icons/location.png", + width: 26, + height: 26, + ); } else { const config = ImageConfiguration(size: Size(48, 48)); - departureIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/pickup.png"); - destinationIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/dropoff.png"); - taxiIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/ic_taxi.png"); - stopIcon = await BitmapDescriptor.fromAssetImage(config, "assets/icons/location.png"); + departureIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/pickup.png", + ); + destinationIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/dropoff.png", + ); + taxiIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/ic_taxi.png", + ); + stopIcon = await BitmapDescriptor.fromAssetImage( + config, + "assets/icons/location.png", + ); } } catch (e) { print('Error loading icons: $e'); @@ -851,8 +1144,12 @@ class CabBookingController extends GetxController { } void clearMapDataIfLocationsRemoved() { - final isSourceEmpty = departureLatLongOsm.value.latitude == 0.0 && departureLatLongOsm.value.longitude == 0.0; - final isDestinationEmpty = destinationLatLongOsm.value.latitude == 0.0 && destinationLatLongOsm.value.longitude == 0.0; + final isSourceEmpty = + departureLatLongOsm.value.latitude == 0.0 && + departureLatLongOsm.value.longitude == 0.0; + final isDestinationEmpty = + destinationLatLongOsm.value.latitude == 0.0 && + destinationLatLongOsm.value.longitude == 0.0; if (isSourceEmpty || isDestinationEmpty) { // Clear polylines @@ -881,7 +1178,9 @@ class CabBookingController extends GetxController { // Remove marker if (Constant.selectedMapType == 'osm') { - osmMarker.removeWhere((marker) => marker.point == departureLatLongOsm.value); + osmMarker.removeWhere( + (marker) => marker.point == departureLatLongOsm.value, + ); } else { markers.removeWhere((marker) => marker.markerId.value == 'Departure'); } @@ -897,7 +1196,9 @@ class CabBookingController extends GetxController { destinationTextEditController.value.clear(); if (Constant.selectedMapType == 'osm') { - osmMarker.removeWhere((marker) => marker.point == destinationLatLongOsm.value); + osmMarker.removeWhere( + (marker) => marker.point == destinationLatLongOsm.value, + ); } else { markers.removeWhere((marker) => marker.markerId.value == 'Destination'); } @@ -907,9 +1208,16 @@ class CabBookingController extends GetxController { } Future searchPlaceNameOSM() async { - final url = Uri.parse('https://nominatim.openstreetmap.org/reverse?lat=${departureLatLongOsm.value.latitude}&lon=${departureLatLongOsm.value.longitude}&format=json'); + final url = Uri.parse( + 'https://nominatim.openstreetmap.org/reverse?lat=${departureLatLongOsm.value.latitude}&lon=${departureLatLongOsm.value.longitude}&format=json', + ); - final response = await http.get(url, headers: {'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)'}); + final response = await http.get( + url, + headers: { + 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', + }, + ); if (response.statusCode == 200) { log("response.body :: ${response.body}"); @@ -922,7 +1230,9 @@ class CabBookingController extends GetxController { final lat = departureLatLong.value.latitude; final lng = departureLatLong.value.longitude; - final url = Uri.parse('https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=${Constant.mapAPIKey}'); + final url = Uri.parse( + 'https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=${Constant.mapAPIKey}', + ); final response = await http.get(url); @@ -965,19 +1275,45 @@ class CabBookingController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -1019,20 +1355,32 @@ class CabBookingController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -1078,7 +1426,10 @@ class CabBookingController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -1088,8 +1439,14 @@ class CabBookingController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -1102,12 +1459,20 @@ class CabBookingController extends GetxController { }, ], "payer": {"email": userModel.value.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, "auto_return": "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -1165,9 +1530,12 @@ class CabBookingController extends GetxController { ///PayStack Payment Method Future payStackPayment(String totalAmount) async { - await PayStackURLGen.payStackURLGen(amount: (double.parse(totalAmount) * 100).toString(), currency: "ZAR", secretKey: payStackModel.value.secretKey.toString(), userModel: userModel.value).then(( - value, - ) async { + await PayStackURLGen.payStackURLGen( + amount: (double.parse(totalAmount) * 100).toString(), + currency: "ZAR", + secretKey: payStackModel.value.secretKey.toString(), + userModel: userModel.value, + ).then((value) async { if (value != null) { PayStackUrlModel payStackModel0 = value; Get.to( @@ -1187,15 +1555,23 @@ class CabBookingController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -1208,14 +1584,19 @@ class CabBookingController extends GetxController { "phonenumber": userModel.value.phoneNumber, // Add a real phone number "name": userModel.value.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1244,8 +1625,14 @@ class CabBookingController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: userModel.value).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: userModel.value, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -1284,7 +1671,14 @@ class CabBookingController extends GetxController { // }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -1320,24 +1714,38 @@ class CabBookingController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), "checksum_value": checkSum}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -1355,9 +1763,12 @@ class CabBookingController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -1375,7 +1786,10 @@ class CabBookingController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': userModel.value.phoneNumber, 'email': userModel.value.email}, + 'prefill': { + 'contact': userModel.value.phoneNumber, + 'email': userModel.value.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -1410,7 +1824,10 @@ class CabBookingController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -1428,15 +1845,30 @@ class CabBookingController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -1444,7 +1876,9 @@ class CabBookingController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -1461,13 +1895,30 @@ class CabBookingController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1479,13 +1930,22 @@ class CabBookingController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth!}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -1496,17 +1956,32 @@ class CabBookingController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; - String apiUrl = orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -1521,7 +1996,11 @@ class CabBookingController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -1535,7 +2014,9 @@ class CabBookingController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -1552,7 +2033,13 @@ class CabBookingController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -1569,7 +2056,9 @@ class CabBookingController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -1582,7 +2071,11 @@ class CabBookingController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/cab_coupon_code_controller.dart b/lib/controllers/cab_coupon_code_controller.dart index 8d57707..2da0007 100644 --- a/lib/controllers/cab_coupon_code_controller.dart +++ b/lib/controllers/cab_coupon_code_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class CabCouponCodeController extends GetxController { // Add your methods and properties here @@ -12,10 +12,10 @@ class CabCouponCodeController extends GetxController { super.onInit(); } - - void getData(){ + void getData() { getCouponCode(); } + RxBool isLoading = true.obs; RxList cabCouponList = [].obs; diff --git a/lib/controllers/cab_dashboard_controller.dart b/lib/controllers/cab_dashboard_controller.dart index 2bd4e9b..24e33cf 100644 --- a/lib/controllers/cab_dashboard_controller.dart +++ b/lib/controllers/cab_dashboard_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/screen_ui/cab_service_screens/cab_home_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/profile_screen/profile_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../screen_ui/cab_service_screens/my_cab_booking_screen.dart'; class CabDashboardController extends GetxController { @@ -15,15 +15,26 @@ class CabDashboardController extends GetxController { void onInit() { getTaxList(); if (Constant.walletSetting == false) { - pageList.value = [CabHomeScreen(), const MyCabBookingScreen(), const ProfileScreen()]; + pageList.value = [ + CabHomeScreen(), + const MyCabBookingScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [CabHomeScreen(), const MyCabBookingScreen(), const WalletScreen(), const ProfileScreen()]; + pageList.value = [ + CabHomeScreen(), + const MyCabBookingScreen(), + const WalletScreen(), + const ProfileScreen(), + ]; } super.onInit(); } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/cab_home_controller.dart b/lib/controllers/cab_home_controller.dart index ba4361c..8ece16f 100644 --- a/lib/controllers/cab_home_controller.dart +++ b/lib/controllers/cab_home_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/models/banner_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class CabHomeController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/cab_order_details_controller.dart b/lib/controllers/cab_order_details_controller.dart index 0106e98..e2f5e3b 100644 --- a/lib/controllers/cab_order_details_controller.dart +++ b/lib/controllers/cab_order_details_controller.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:customer/constant/constant.dart'; import 'package:customer/models/rating_model.dart'; import 'package:flutter_polyline_points/flutter_polyline_points.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:google_maps_flutter/google_maps_flutter.dart' as gmap; import 'package:latlong2/latlong.dart' as osm; @@ -56,14 +56,18 @@ class CabOrderDetailsController extends GetxController { Future fetchDriverDetails() async { if (cabOrder.value.driverId != null) { - await FireStoreUtils.getUserProfile(cabOrder.value.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile(cabOrder.value.driverId ?? '').then(( + value, + ) { if (value != null) { driverUser.value = value; } }); print(driverUser.value.toJson()); - await FireStoreUtils.getReviewsbyID(cabOrder.value.id.toString()).then((value) { + await FireStoreUtils.getReviewsbyID(cabOrder.value.id.toString()).then(( + value, + ) { if (value != null) { ratingModel.value = value; } @@ -79,7 +83,12 @@ class CabOrderDetailsController extends GetxController { if (cabOrder.value.taxSetting != null) { for (var element in cabOrder.value.taxSetting!) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } } @@ -94,8 +103,20 @@ class CabOrderDetailsController extends GetxController { final destLng = cabOrder.value.destinationLocation!.longitude; googleMarkers.value = { - gmap.Marker(markerId: const gmap.MarkerId('source'), position: gmap.LatLng(sourceLat!, sourceLng!), icon: gmap.BitmapDescriptor.defaultMarkerWithHue(gmap.BitmapDescriptor.hueGreen)), - gmap.Marker(markerId: const gmap.MarkerId('destination'), position: gmap.LatLng(destLat!, destLng!), icon: gmap.BitmapDescriptor.defaultMarkerWithHue(gmap.BitmapDescriptor.hueRed)), + gmap.Marker( + markerId: const gmap.MarkerId('source'), + position: gmap.LatLng(sourceLat!, sourceLng!), + icon: gmap.BitmapDescriptor.defaultMarkerWithHue( + gmap.BitmapDescriptor.hueGreen, + ), + ), + gmap.Marker( + markerId: const gmap.MarkerId('destination'), + position: gmap.LatLng(destLat!, destLng!), + icon: gmap.BitmapDescriptor.defaultMarkerWithHue( + gmap.BitmapDescriptor.hueRed, + ), + ), }; } @@ -104,7 +125,8 @@ class CabOrderDetailsController extends GetxController { final src = cabOrder.value.sourceLocation; final dest = cabOrder.value.destinationLocation; - final url = "https://maps.googleapis.com/maps/api/directions/json?origin=${src!.latitude},${src.longitude}&destination=${dest!.latitude},${dest.longitude}&key=$googleApiKey"; + final url = + "https://maps.googleapis.com/maps/api/directions/json?origin=${src!.latitude},${src.longitude}&destination=${dest!.latitude},${dest.longitude}&key=$googleApiKey"; final response = await http.get(Uri.parse(url)); final data = jsonDecode(response.body); @@ -113,9 +135,19 @@ class CabOrderDetailsController extends GetxController { final points = data["routes"][0]["overview_polyline"]["points"]; final polylinePoints = PolylinePoints.decodePolyline(points); - final polylineCoords = polylinePoints.map((p) => gmap.LatLng(p.latitude, p.longitude)).toList(); + final polylineCoords = + polylinePoints + .map((p) => gmap.LatLng(p.latitude, p.longitude)) + .toList(); - googlePolylines.value = {gmap.Polyline(polylineId: const gmap.PolylineId("google_route"), color: AppThemeData.onDemandDark100, width: 5, points: polylineCoords)}; + googlePolylines.value = { + gmap.Polyline( + polylineId: const gmap.PolylineId("google_route"), + color: AppThemeData.onDemandDark100, + width: 5, + points: polylineCoords, + ), + }; } } @@ -124,15 +156,20 @@ class CabOrderDetailsController extends GetxController { final src = cabOrder.value.sourceLocation; final dest = cabOrder.value.destinationLocation; - final url = "http://router.project-osrm.org/route/v1/driving/${src!.longitude},${src.latitude};${dest!.longitude},${dest.latitude}?overview=full&geometries=geojson"; + final url = + "http://router.project-osrm.org/route/v1/driving/${src!.longitude},${src.latitude};${dest!.longitude},${dest.latitude}?overview=full&geometries=geojson"; final response = await http.get(Uri.parse(url)); final data = jsonDecode(response.body); if (data["routes"].isNotEmpty) { - final coords = data["routes"][0]["geometry"]["coordinates"] as List; + final coords = + data["routes"][0]["geometry"]["coordinates"] as List; - osmPolyline.value = coords.map((c) => osm.LatLng(c[1].toDouble(), c[0].toDouble())).toList(); + osmPolyline.value = + coords + .map((c) => osm.LatLng(c[1].toDouble(), c[0].toDouble())) + .toList(); } } } diff --git a/lib/controllers/cab_rental_dashboard_controllers.dart b/lib/controllers/cab_rental_dashboard_controllers.dart index add5017..1e0eda6 100644 --- a/lib/controllers/cab_rental_dashboard_controllers.dart +++ b/lib/controllers/cab_rental_dashboard_controllers.dart @@ -3,8 +3,7 @@ import 'package:customer/screen_ui/multi_vendor_service/profile_screen/profile_s import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/screen_ui/rental_service/rental_home_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../screen_ui/rental_service/my_rental_booking_screen.dart'; class CabRentalDashboardControllers extends GetxController { @@ -17,15 +16,26 @@ class CabRentalDashboardControllers extends GetxController { // TODO: implement onInit getTaxList(); if (Constant.walletSetting == false) { - pageList.value = [RentalHomeScreen(), MyRentalBookingScreen(), const ProfileScreen()]; + pageList.value = [ + RentalHomeScreen(), + MyRentalBookingScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [RentalHomeScreen(), MyRentalBookingScreen(), const WalletScreen(), const ProfileScreen()]; + pageList.value = [ + RentalHomeScreen(), + MyRentalBookingScreen(), + const WalletScreen(), + const ProfileScreen(), + ]; } super.onInit(); } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/cab_review_controller.dart b/lib/controllers/cab_review_controller.dart index bbd1b20..e5218bb 100644 --- a/lib/controllers/cab_review_controller.dart +++ b/lib/controllers/cab_review_controller.dart @@ -2,7 +2,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:customer/models/cab_order_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/collection_name.dart'; import '../models/rating_model.dart'; import '../models/user_model.dart'; @@ -44,12 +44,17 @@ class CabReviewController extends GetxController { } }); - await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then(( + value, + ) { if (value != null) { driverUser.value = value; - final int userReviewsCount = int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? 0; - final int userReviewsSum = int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; + final int userReviewsCount = + int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? + 0; + final int userReviewsSum = + int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; if (ratingModel.value != null) { final int oldRating = ratingModel.value?.rating?.toInt() ?? 0; @@ -74,7 +79,9 @@ class CabReviewController extends GetxController { ShowToastDialog.showLoader("Submit in...".tr()); - final user = await FireStoreUtils.getUserProfile(order.value?.driverId ?? ''); + final user = await FireStoreUtils.getUserProfile( + order.value?.driverId ?? '', + ); if (user != null) { user.reviewsCount = (futureCount.value + 1).toString(); @@ -91,7 +98,8 @@ class CabReviewController extends GetxController { driverId: ratingModel.value!.driverId, customerId: ratingModel.value!.customerId, vendorId: ratingModel.value?.vendorId, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); @@ -102,7 +110,8 @@ class CabReviewController extends GetxController { } } else { /// New review - final docRef = FireStoreUtils.fireStore.collection(CollectionName.itemsReview).doc(); + final docRef = + FireStoreUtils.fireStore.collection(CollectionName.itemsReview).doc(); final newRating = RatingModel( id: docRef.id, comment: comment.value.text, @@ -111,7 +120,8 @@ class CabReviewController extends GetxController { orderId: order.value?.id, driverId: order.value?.driverId.toString(), customerId: Constant.userModel?.id, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); diff --git a/lib/controllers/cart_controller.dart b/lib/controllers/cart_controller.dart index 8998fa7..5dc45ff 100644 --- a/lib/controllers/cart_controller.dart +++ b/lib/controllers/cart_controller.dart @@ -17,7 +17,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; @@ -108,7 +108,9 @@ class CartController extends GetxController { cartItem.addAll(event); if (cartItem.isNotEmpty) { - await FireStoreUtils.getVendorById(cartItem.first.vendorID.toString()).then((value) { + await FireStoreUtils.getVendorById( + cartItem.first.vendorID.toString(), + ).then((value) { if (value != null) { vendorModel.value = value; } @@ -116,9 +118,14 @@ class CartController extends GetxController { } calculatePrice(); }); - selectedFoodType.value = Preferences.getString(Preferences.foodDeliveryType, defaultValue: "Delivery"); + selectedFoodType.value = Preferences.getString( + Preferences.foodDeliveryType, + defaultValue: "Delivery", + ); - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { if (value != null) { userModel.value = value; } @@ -127,16 +134,22 @@ class CartController extends GetxController { await FireStoreUtils.getDeliveryCharge().then((value) { if (value != null) { deliveryChargeModel.value = value; - print("===> Delivery Charge Model: ${deliveryChargeModel.value.toJson()}"); + print( + "===> Delivery Charge Model: ${deliveryChargeModel.value.toJson()}", + ); calculatePrice(); } }); - await FireStoreUtils.getAllVendorPublicCoupons(vendorModel.value.id.toString()).then((value) { + await FireStoreUtils.getAllVendorPublicCoupons( + vendorModel.value.id.toString(), + ).then((value) { couponList.value = value; }); - await FireStoreUtils.getAllVendorCoupons(vendorModel.value.id.toString()).then((value) { + await FireStoreUtils.getAllVendorCoupons( + vendorModel.value.id.toString(), + ).then((value) { allCouponList.value = value; }); } @@ -150,8 +163,11 @@ class CartController extends GetxController { totalAmount.value = 0.0; if (cartItem.isNotEmpty) { - if (Constant.sectionConstantModel!.serviceTypeFlag == "ecommerce-service") { - deliveryCharges.value = double.parse(Constant.sectionConstantModel!.delivery_charge ?? "0"); + if (Constant.sectionConstantModel!.serviceTypeFlag == + "ecommerce-service") { + deliveryCharges.value = double.parse( + Constant.sectionConstantModel!.delivery_charge ?? "0", + ); } else { if (selectedFoodType.value == "Delivery") { totalDistance.value = double.parse( @@ -162,26 +178,50 @@ class CartController extends GetxController { lng2: vendorModel.value.longitude.toString(), ), ); - if (vendorModel.value.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true) { + if (vendorModel.value.isSelfDelivery == true && + Constant.isSelfDeliveryFeature == true) { deliveryCharges.value = 0.0; } else if (deliveryChargeModel.value.vendorCanModify == false) { - if (totalDistance.value > deliveryChargeModel.value.minimumDeliveryChargesWithinKm!) { - deliveryCharges.value = totalDistance.value * deliveryChargeModel.value.deliveryChargesPerKm!; + if (totalDistance.value > + deliveryChargeModel.value.minimumDeliveryChargesWithinKm!) { + deliveryCharges.value = + totalDistance.value * + deliveryChargeModel.value.deliveryChargesPerKm!; } else { - deliveryCharges.value = (deliveryChargeModel.value.minimumDeliveryCharges)!.toDouble(); + deliveryCharges.value = + (deliveryChargeModel.value.minimumDeliveryCharges)! + .toDouble(); } } else { if (vendorModel.value.deliveryCharge != null) { - if (totalDistance.value > vendorModel.value.deliveryCharge!.minimumDeliveryChargesWithinKm!) { - deliveryCharges.value = (totalDistance.value * vendorModel.value.deliveryCharge!.deliveryChargesPerKm!).toDouble(); + if (totalDistance.value > + vendorModel + .value + .deliveryCharge! + .minimumDeliveryChargesWithinKm!) { + deliveryCharges.value = + (totalDistance.value * + vendorModel + .value + .deliveryCharge! + .deliveryChargesPerKm!) + .toDouble(); } else { - deliveryCharges.value = vendorModel.value.deliveryCharge!.minimumDeliveryCharges!.toDouble(); + deliveryCharges.value = + vendorModel.value.deliveryCharge!.minimumDeliveryCharges! + .toDouble(); } } else { - if (totalDistance.value > deliveryChargeModel.value.minimumDeliveryChargesWithinKm!) { - deliveryCharges.value = (totalDistance.value * deliveryChargeModel.value.deliveryChargesPerKm!).toDouble(); + if (totalDistance.value > + deliveryChargeModel.value.minimumDeliveryChargesWithinKm!) { + deliveryCharges.value = + (totalDistance.value * + deliveryChargeModel.value.deliveryChargesPerKm!) + .toDouble(); } else { - deliveryCharges.value = deliveryChargeModel.value.minimumDeliveryCharges!.toDouble(); + deliveryCharges.value = + deliveryChargeModel.value.minimumDeliveryCharges! + .toDouble(); } } } @@ -195,21 +235,29 @@ class CartController extends GetxController { if (double.parse(element.discountPrice.toString()) <= 0) { subTotal.value = subTotal.value + - double.parse(element.price.toString()) * double.parse(element.quantity.toString()) + - (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); + double.parse(element.price.toString()) * + double.parse(element.quantity.toString()) + + (double.parse(element.extrasPrice.toString()) * + double.parse(element.quantity.toString())); } else { subTotal.value = subTotal.value + - double.parse(element.discountPrice.toString()) * double.parse(element.quantity.toString()) + - (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); + double.parse(element.discountPrice.toString()) * + double.parse(element.quantity.toString()) + + (double.parse(element.extrasPrice.toString()) * + double.parse(element.quantity.toString())); } } if (selectedCouponModel.value.id != null) { - couponAmount.value = Constant.calculateDiscount(amount: subTotal.value.toString(), offerModel: selectedCouponModel.value); + couponAmount.value = Constant.calculateDiscount( + amount: subTotal.value.toString(), + offerModel: selectedCouponModel.value, + ); } - if (vendorModel.value.specialDiscountEnable == true && Constant.specialDiscountOffer == true) { + if (vendorModel.value.specialDiscountEnable == true && + Constant.specialDiscountOffer == true) { final now = DateTime.now(); var day = DateFormat('EEEE', 'en_US').format(now); var date = DateFormat('dd-MM-yyyy').format(now); @@ -218,13 +266,20 @@ class CartController extends GetxController { if (element.timeslot!.isNotEmpty) { for (var element in element.timeslot!) { if (element.discountType == "delivery") { - var start = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.from}"); - var end = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.to}"); + var start = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.from}"); + var end = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.to}"); if (isCurrentDateInRange(start, end)) { - specialDiscount.value = double.parse(element.discount.toString()); + specialDiscount.value = double.parse( + element.discount.toString(), + ); specialType.value = element.type.toString(); if (element.type == "percentage") { - specialDiscountAmount.value = subTotal * specialDiscount.value / 100; + specialDiscountAmount.value = + subTotal * specialDiscount.value / 100; } else { specialDiscountAmount.value = specialDiscount.value; } @@ -240,10 +295,23 @@ class CartController extends GetxController { } for (var element in Constant.taxList) { - taxAmount.value = taxAmount.value + Constant.calculateTax(amount: (subTotal.value - couponAmount.value - specialDiscountAmount.value).toString(), taxModel: element); + taxAmount.value = + taxAmount.value + + Constant.calculateTax( + amount: + (subTotal.value - + couponAmount.value - + specialDiscountAmount.value) + .toString(), + taxModel: element, + ); } - totalAmount.value = (subTotal.value - couponAmount.value - specialDiscountAmount.value) + taxAmount.value + deliveryCharges.value + deliveryTips.value; + totalAmount.value = + (subTotal.value - couponAmount.value - specialDiscountAmount.value) + + taxAmount.value + + deliveryCharges.value + + deliveryTips.value; getCashback(); } @@ -264,17 +332,31 @@ class CartController extends GetxController { if (startDate == null || endDate == null) continue; - final withinDateRange = startDate.toDate().isBefore(now) && endDate.toDate().isAfter(now); - final meetsMinAmount = orderTotal >= (cashback.minimumPurchaseAmount ?? 0); + final withinDateRange = + startDate.toDate().isBefore(now) && endDate.toDate().isAfter(now); + final meetsMinAmount = + orderTotal >= (cashback.minimumPurchaseAmount ?? 0); final allPayment = cashback.allPayment ?? false; - final paymentMatch = allPayment || (cashback.paymentMethods ?? []).contains(paymentMethod); + final paymentMatch = + allPayment || + (cashback.paymentMethods ?? []).contains(paymentMethod); final allCustomer = cashback.allCustomer ?? false; - final customerMatch = allCustomer || (cashback.customerIds ?? []).contains(FireStoreUtils.getCurrentUid()); + final customerMatch = + allCustomer || + (cashback.customerIds ?? []).contains( + FireStoreUtils.getCurrentUid(), + ); - final redeemData = await FireStoreUtils.getRedeemedCashbacks(cashback.id ?? ''); + final redeemData = await FireStoreUtils.getRedeemedCashbacks( + cashback.id ?? '', + ); final underLimit = redeemData.length < (cashback.redeemLimit ?? 0); - if (withinDateRange && meetsMinAmount && paymentMatch && customerMatch && underLimit) { + if (withinDateRange && + meetsMinAmount && + paymentMatch && + customerMatch && + underLimit) { eligibleCashbacks.add(cashback); } } @@ -312,7 +394,11 @@ class CartController extends GetxController { } } - Future addToCart({required CartProductModel cartProductModel, required bool isIncrement, required int quantity}) async { + Future addToCart({ + required CartProductModel cartProductModel, + required bool isIncrement, + required int quantity, + }) async { if (isIncrement) { cartProvider.addToCart(Get.context!, cartProductModel, quantity); } else { @@ -325,10 +411,13 @@ class CartController extends GetxController { Future placeOrder() async { if (selectedPaymentMethod.value == PaymentGateway.wallet.name) { - if (double.parse(userModel.value.walletAmount.toString()) >= totalAmount.value) { + if (double.parse(userModel.value.walletAmount.toString()) >= + totalAmount.value) { setOrder(); } else { - ShowToastDialog.showToast("You don't have sufficient wallet balance to place order".tr()); + ShowToastDialog.showToast( + "You don't have sufficient wallet balance to place order".tr(), + ); } } else { setOrder(); @@ -338,11 +427,19 @@ class CartController extends GetxController { Future setOrder() async { ShowToastDialog.showLoader("Please wait...".tr()); - if ((Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel?.adminCommision?.isEnabled == true) && vendorModel.value.subscriptionPlan != null) { - await FireStoreUtils.getVendorById(vendorModel.value.id!).then((vender) async { - if (vender?.subscriptionTotalOrders == '0' || vender?.subscriptionTotalOrders == null) { + if ((Constant.isSubscriptionModelApplied == true || + Constant.sectionConstantModel?.adminCommision?.isEnabled == true) && + vendorModel.value.subscriptionPlan != null) { + await FireStoreUtils.getVendorById(vendorModel.value.id!).then(( + vender, + ) async { + if (vender?.subscriptionTotalOrders == '0' || + vender?.subscriptionTotalOrders == null) { ShowToastDialog.closeLoader(); - ShowToastDialog.showToast("This vendor has reached their maximum order capacity. Please select a different vendor or try again later.".tr()); + ShowToastDialog.showToast( + "This vendor has reached their maximum order capacity. Please select a different vendor or try again later." + .tr(), + ); return; } }); @@ -356,7 +453,11 @@ class CartController extends GetxController { tempProduc.add(tempCart); } - Map specialDiscountMap = {'special_discount': specialDiscountAmount.value, 'special_discount_label': specialDiscount.value, 'specialType': specialType.value}; + Map specialDiscountMap = { + 'special_discount': specialDiscountAmount.value, + 'special_discount_label': specialDiscount.value, + 'specialType': specialType.value, + }; OrderModel orderModel = OrderModel(); orderModel.id = Constant.getUuid(); @@ -391,8 +492,12 @@ class CartController extends GetxController { orderModel.notes = reMarkController.value.text; orderModel.takeAway = selectedFoodType.value == "Delivery" ? false : true; orderModel.createdAt = Timestamp.now(); - orderModel.scheduleTime = deliveryType.value == "schedule" ? Timestamp.fromDate(scheduleDateTime.value) : null; - orderModel.cashback = bestCashback.value.id == null ? null : bestCashback.value; + orderModel.scheduleTime = + deliveryType.value == "schedule" + ? Timestamp.fromDate(scheduleDateTime.value) + : null; + orderModel.cashback = + bestCashback.value.id == null ? null : bestCashback.value; if (selectedPaymentMethod.value == PaymentGateway.wallet.name) { WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), @@ -407,33 +512,57 @@ class CartController extends GetxController { paymentStatus: "success".tr(), ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()).then((value) {}); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ).then((value) {}); } }); } for (int i = 0; i < tempProduc.length; i++) { - await FireStoreUtils.getProductById(tempProduc[i].id!.split('~').first).then((value) async { + await FireStoreUtils.getProductById( + tempProduc[i].id!.split('~').first, + ).then((value) async { ProductModel? productModel = value; if (tempProduc[i].variantInfo != null) { if (productModel!.itemAttribute != null) { - for (int j = 0; j < productModel.itemAttribute!.variants!.length; j++) { - if (productModel.itemAttribute!.variants![j].variantId == tempProduc[i].id!.split('~').last) { - if (productModel.itemAttribute!.variants![j].variantQuantity != "-1") { - productModel.itemAttribute!.variants![j].variantQuantity = (int.parse(productModel.itemAttribute!.variants![j].variantQuantity.toString()) - tempProduc[i].quantity!).toString(); + for ( + int j = 0; + j < productModel.itemAttribute!.variants!.length; + j++ + ) { + if (productModel.itemAttribute!.variants![j].variantId == + tempProduc[i].id!.split('~').last) { + if (productModel.itemAttribute!.variants![j].variantQuantity != + "-1") { + productModel.itemAttribute!.variants![j].variantQuantity = + (int.parse( + productModel + .itemAttribute! + .variants![j] + .variantQuantity + .toString(), + ) - + tempProduc[i].quantity!) + .toString(); } } } } else { if (productModel.quantity != -1) { - productModel.quantity = (productModel.quantity! - tempProduc[i].quantity!); + productModel.quantity = + (productModel.quantity! - tempProduc[i].quantity!); } } } else { if (productModel!.quantity != -1) { - productModel.quantity = (productModel.quantity! - tempProduc[i].quantity!); + productModel.quantity = + (productModel.quantity! - tempProduc[i].quantity!); } } @@ -451,18 +580,31 @@ class CartController extends GetxController { await FireStoreUtils.setCashbackRedeemModel(cashbackRedeemModel); } await FireStoreUtils.setOrder(orderModel).then((value) async { - await FireStoreUtils.getUserProfile(orderModel.vendor!.author.toString()).then((value) async { + await FireStoreUtils.getUserProfile( + orderModel.vendor!.author.toString(), + ).then((value) async { if (value != null) { if (orderModel.scheduleTime != null) { - await SendNotification.sendFcmMessage(Constant.scheduleOrder, value.fcmToken ?? '', {}); + await SendNotification.sendFcmMessage( + Constant.scheduleOrder, + value.fcmToken ?? '', + {}, + ); } else { - await SendNotification.sendFcmMessage(Constant.newOrderPlaced, value.fcmToken ?? '', {}); + await SendNotification.sendFcmMessage( + Constant.newOrderPlaced, + value.fcmToken ?? '', + {}, + ); } } }); await Constant.sendOrderEmail(orderModel: orderModel); ShowToastDialog.closeLoader(); - Get.off(const OrderPlacingScreen(), arguments: {"orderModel": orderModel}); + Get.off( + const OrderPlacingScreen(), + arguments: {"orderModel": orderModel}, + ); }); } @@ -483,19 +625,45 @@ class CartController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -537,20 +705,32 @@ class CartController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -596,7 +776,10 @@ class CartController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -606,8 +789,14 @@ class CartController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -620,12 +809,20 @@ class CartController extends GetxController { }, ], "payer": {"email": userModel.value.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, "auto_return": "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -683,9 +880,12 @@ class CartController extends GetxController { ///PayStack Payment Method Future payStackPayment(String totalAmount) async { - await PayStackURLGen.payStackURLGen(amount: (double.parse(totalAmount) * 100).toString(), currency: "ZAR", secretKey: payStackModel.value.secretKey.toString(), userModel: userModel.value).then(( - value, - ) async { + await PayStackURLGen.payStackURLGen( + amount: (double.parse(totalAmount) * 100).toString(), + currency: "ZAR", + secretKey: payStackModel.value.secretKey.toString(), + userModel: userModel.value, + ).then((value) async { if (value != null) { PayStackUrlModel payStackModel0 = value; Get.to( @@ -705,15 +905,23 @@ class CartController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -726,14 +934,19 @@ class CartController extends GetxController { "phonenumber": userModel.value.phoneNumber, // Add a real phone number "name": userModel.value.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -762,8 +975,14 @@ class CartController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: userModel.value).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: userModel.value, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -783,26 +1002,50 @@ class CartController extends GetxController { final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString()}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + }, ); final data = jsonDecode(response.body); - await verifyCheckSum(checkSum: data["code"], amount: amount, orderId: orderId).then((value) { + await verifyCheckSum( + checkSum: data["code"], + amount: amount, + orderId: orderId, + ).then((value) { initiatePayment(amount: amount, orderId: orderId).then((value) { String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } GetPaymentTxtTokenModel result = value; - startTransaction(context, txnTokenBy: result.body.txnToken ?? '', orderId: orderId, amount: amount, callBackURL: callback, isStaging: paytmModel.value.isSandboxEnabled); + startTransaction( + context, + txnTokenBy: result.body.txnToken ?? '', + orderId: orderId, + amount: amount, + callBackURL: callback, + isStaging: paytmModel.value.isSandboxEnabled, + ); }); }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -838,24 +1081,38 @@ class CartController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), "checksum_value": checkSum}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -873,9 +1130,12 @@ class CartController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -893,7 +1153,10 @@ class CartController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': userModel.value.phoneNumber, 'email': userModel.value.email}, + 'prefill': { + 'contact': userModel.value.phoneNumber, + 'email': userModel.value.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -927,7 +1190,10 @@ class CartController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -945,15 +1211,30 @@ class CartController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -961,7 +1242,9 @@ class CartController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -978,13 +1261,30 @@ class CartController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -996,13 +1296,22 @@ class CartController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth!}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -1013,17 +1322,32 @@ class CartController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; - String apiUrl = orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -1038,7 +1362,11 @@ class CartController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -1052,7 +1380,9 @@ class CartController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -1069,7 +1399,13 @@ class CartController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -1086,7 +1422,9 @@ class CartController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -1099,7 +1437,11 @@ class CartController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/cashback_controller.dart b/lib/controllers/cashback_controller.dart index 43aa518..786fa55 100644 --- a/lib/controllers/cashback_controller.dart +++ b/lib/controllers/cashback_controller.dart @@ -1,5 +1,5 @@ import '../models/cashback_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../service/fire_store_utils.dart'; class CashbackController extends GetxController { diff --git a/lib/controllers/category_restaurant_controller.dart b/lib/controllers/category_restaurant_controller.dart index bd8e41a..a80b92b 100644 --- a/lib/controllers/category_restaurant_controller.dart +++ b/lib/controllers/category_restaurant_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/models/vendor_model.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../models/vendor_category_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class CategoryRestaurantController extends GetxController { RxBool isLoading = true.obs; @@ -33,9 +33,10 @@ class CategoryRestaurantController extends GetxController { } Future getRestaurant() async { - FireStoreUtils.getAllNearestRestaurantByCategoryId(categoryId: vendorCategoryModel.value.id.toString(), isDining: dineIn.value).listen(( - event, - ) async { + FireStoreUtils.getAllNearestRestaurantByCategoryId( + categoryId: vendorCategoryModel.value.id.toString(), + isDining: dineIn.value, + ).listen((event) async { allNearestRestaurant.clear(); allNearestRestaurant.addAll(event); }); @@ -46,7 +47,10 @@ class CategoryRestaurantController extends GetxController { if (value != null) { for (int i = 0; i < value.length; i++) { if (Constant.isPointInPolygon( - LatLng(Constant.selectedLocation.location!.latitude ?? 0.0, Constant.selectedLocation.location!.longitude ?? 0.0), + LatLng( + Constant.selectedLocation.location!.latitude ?? 0.0, + Constant.selectedLocation.location!.longitude ?? 0.0, + ), value[i].area!, )) { Constant.selectedZone = value[i]; diff --git a/lib/controllers/change_language_controller.dart b/lib/controllers/change_language_controller.dart index aad7891..82be122 100644 --- a/lib/controllers/change_language_controller.dart +++ b/lib/controllers/change_language_controller.dart @@ -2,8 +2,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/language_model.dart'; import '../service/fire_store_utils.dart'; import 'package:customer/utils/preferences.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../constant/collection_name.dart'; class ChangeLanguageController extends GetxController { @@ -20,24 +19,30 @@ class ChangeLanguageController extends GetxController { } Future getLanguage() async { - await FireStoreUtils.fireStore.collection(CollectionName.settings).doc("languages").get().then((event) { - if (event.exists) { - List languageListTemp = event.data()!["list"]; - for (var element in languageListTemp) { - LanguageModel languageModel = LanguageModel.fromJson(element); - languageList.add(languageModel); - } + await FireStoreUtils.fireStore + .collection(CollectionName.settings) + .doc("languages") + .get() + .then((event) { + if (event.exists) { + List languageListTemp = event.data()!["list"]; + for (var element in languageListTemp) { + LanguageModel languageModel = LanguageModel.fromJson(element); + languageList.add(languageModel); + } - if (Preferences.getString(Preferences.languageCodeKey).toString().isNotEmpty) { - LanguageModel pref = Constant.getLanguage(); - for (var element in languageList) { - if (element.slug == pref.slug) { - selectedLanguage.value = element; + if (Preferences.getString( + Preferences.languageCodeKey, + ).toString().isNotEmpty) { + LanguageModel pref = Constant.getLanguage(); + for (var element in languageList) { + if (element.slug == pref.slug) { + selectedLanguage.value = element; + } + } } } - } - } - }); + }); isLoading.value = false; } diff --git a/lib/controllers/chat_controller.dart b/lib/controllers/chat_controller.dart index bce8cf5..c0e2925 100644 --- a/lib/controllers/chat_controller.dart +++ b/lib/controllers/chat_controller.dart @@ -7,7 +7,7 @@ import '../models/conversation_model.dart'; import '../models/inbox_model.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:uuid/uuid.dart'; import '../service/send_notification.dart'; @@ -21,7 +21,11 @@ class ChatController extends GetxController { void onInit() { // TODO: implement onInit if (scrollController.hasClients) { - Timer(const Duration(milliseconds: 500), () => scrollController.jumpTo(scrollController.position.maxScrollExtent)); + Timer( + const Duration(milliseconds: 500), + () => + scrollController.jumpTo(scrollController.position.maxScrollExtent), + ); } getArgument(); super.onInit(); @@ -47,14 +51,20 @@ class ChatController extends GetxController { customerProfileImage.value = argumentData['customerProfileImage'] ?? ""; restaurantId.value = argumentData['restaurantId']; restaurantName.value = argumentData['restaurantName']; - restaurantProfileImage.value = argumentData['restaurantProfileImage'] ?? ""; + restaurantProfileImage.value = + argumentData['restaurantProfileImage'] ?? ""; token.value = argumentData['token'] ?? ""; chatType.value = argumentData['chatType']; } isLoading.value = false; } - Future sendMessage(String message, Url? url, String videoThumbnail, String messageType) async { + Future sendMessage( + String message, + Url? url, + String videoThumbnail, + String messageType, + ) async { InboxModel inboxModel = InboxModel( lastSenderId: customerId.value, customerId: customerId.value, @@ -113,18 +123,23 @@ class ChatController extends GetxController { } //await SendNotification.sendChatFcmMessage(customerName.value, conversationModel.message.toString(), token.value, {}); - await SendNotification.sendChatFcmMessage(customerName.value, conversationModel.message.toString(), token.value, { - "type": "chat", - "chatType": chatType.value, - "orderId": orderId.value, - "customerId": customerId.value, - "customerName": customerName.value, - "customerProfileImage": customerProfileImage.value, - "restaurantId": restaurantId.value, - "restaurantName": restaurantName.value, - "restaurantProfileImage": restaurantProfileImage.value, - "token": token.value, - }); + await SendNotification.sendChatFcmMessage( + customerName.value, + conversationModel.message.toString(), + token.value, + { + "type": "chat", + "chatType": chatType.value, + "orderId": orderId.value, + "customerId": customerId.value, + "customerName": customerName.value, + "customerProfileImage": customerProfileImage.value, + "restaurantId": restaurantId.value, + "restaurantName": restaurantName.value, + "restaurantProfileImage": restaurantProfileImage.value, + "token": token.value, + }, + ); } final ImagePicker imagePicker = ImagePicker(); diff --git a/lib/controllers/complain_controller.dart b/lib/controllers/complain_controller.dart index a76d011..45367eb 100644 --- a/lib/controllers/complain_controller.dart +++ b/lib/controllers/complain_controller.dart @@ -1,6 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/cab_order_model.dart'; import '../service/fire_store_utils.dart'; import '../themes/show_toast_dialog.dart'; @@ -30,7 +30,9 @@ class ComplainController extends GetxController { Future getComplain() async { isLoading.value = true; try { - final data = await FireStoreUtils.getRideComplainData(order.value.id ?? ''); + final data = await FireStoreUtils.getRideComplainData( + order.value.id ?? '', + ); if (data != null) { title.value.text = data['title'] ?? ''; comment.value.text = data['description'] ?? ''; @@ -59,7 +61,9 @@ class ComplainController extends GetxController { try { // Check if complaint already exists - bool exists = await FireStoreUtils.isRideComplainAdded(order.value.id ?? ''); + bool exists = await FireStoreUtils.isRideComplainAdded( + order.value.id ?? '', + ); if (!exists) { await FireStoreUtils.setRideComplain( @@ -67,13 +71,19 @@ class ComplainController extends GetxController { title: title.value.text.trim(), description: comment.value.text.trim(), customerID: order.value.authorID ?? '', - customerName: "${order.value.author?.firstName ?? ''} ${order.value.author?.lastName ?? ''}".trim(), + customerName: + "${order.value.author?.firstName ?? ''} ${order.value.author?.lastName ?? ''}" + .trim(), driverID: order.value.driverId ?? '', - driverName: "${order.value.driver?.firstName ?? ''} ${order.value.driver?.lastName ?? ''}".trim(), + driverName: + "${order.value.driver?.firstName ?? ''} ${order.value.driver?.lastName ?? ''}" + .trim(), ); ShowToastDialog.closeLoader(); - ShowToastDialog.showToast("Your complaint has been submitted to admin".tr()); + ShowToastDialog.showToast( + "Your complaint has been submitted to admin".tr(), + ); Get.back(); } else { ShowToastDialog.closeLoader(); diff --git a/lib/controllers/dash_board_controller.dart b/lib/controllers/dash_board_controller.dart index ae6445f..405df62 100644 --- a/lib/controllers/dash_board_controller.dart +++ b/lib/controllers/dash_board_controller.dart @@ -6,7 +6,7 @@ import '../screen_ui/multi_vendor_service/order_list_screen/order_screen.dart'; import '../screen_ui/multi_vendor_service/profile_screen/profile_screen.dart'; import '../screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DashBoardController extends GetxController { RxInt selectedIndex = 0.obs; @@ -19,22 +19,46 @@ class DashBoardController extends GetxController { getTaxList(); if (Constant.sectionConstantModel!.theme == "theme_2") { if (Constant.walletSetting == false) { - pageList.value = [const HomeScreen(), const FavouriteScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeScreen(), + const FavouriteScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [const HomeScreen(), const FavouriteScreen(), const WalletScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeScreen(), + const FavouriteScreen(), + const WalletScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } } else { if (Constant.walletSetting == false) { - pageList.value = [const HomeScreenTwo(), const FavouriteScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeScreenTwo(), + const FavouriteScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [const HomeScreenTwo(), const FavouriteScreen(), const WalletScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeScreenTwo(), + const FavouriteScreen(), + const WalletScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } } super.onInit(); } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/dash_board_ecommarce_controller.dart b/lib/controllers/dash_board_ecommarce_controller.dart index 02bb9ce..647f120 100644 --- a/lib/controllers/dash_board_ecommarce_controller.dart +++ b/lib/controllers/dash_board_ecommarce_controller.dart @@ -5,7 +5,7 @@ import '../screen_ui/multi_vendor_service/order_list_screen/order_screen.dart'; import '../screen_ui/multi_vendor_service/profile_screen/profile_screen.dart'; import '../screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DashBoardEcommerceController extends GetxController { RxInt selectedIndex = 0.obs; @@ -17,15 +17,28 @@ class DashBoardEcommerceController extends GetxController { // TODO: implement onInit getTaxList(); if (Constant.walletSetting == false) { - pageList.value = [const HomeECommerceScreen(), const FavouriteScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeECommerceScreen(), + const FavouriteScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [const HomeECommerceScreen(), const FavouriteScreen(), const WalletScreen(), const OrderScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeECommerceScreen(), + const FavouriteScreen(), + const WalletScreen(), + const OrderScreen(), + const ProfileScreen(), + ]; } super.onInit(); } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/dine_in_booking_controller.dart b/lib/controllers/dine_in_booking_controller.dart index e273284..4f31c69 100644 --- a/lib/controllers/dine_in_booking_controller.dart +++ b/lib/controllers/dine_in_booking_controller.dart @@ -1,6 +1,6 @@ import '../models/dine_in_booking_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DineInBookingController extends GetxController { RxBool isLoading = true.obs; @@ -18,16 +18,12 @@ class DineInBookingController extends GetxController { } Future getDineInBooking() async { - await FireStoreUtils.getDineInBooking(true).then( - (value) { - featureList.value = value; - }, - ); - await FireStoreUtils.getDineInBooking(false).then( - (value) { - historyList.value = value; - }, - ); + await FireStoreUtils.getDineInBooking(true).then((value) { + featureList.value = value; + }); + await FireStoreUtils.getDineInBooking(false).then((value) { + historyList.value = value; + }); isLoading.value = false; } diff --git a/lib/controllers/dine_in_booking_details_controller.dart b/lib/controllers/dine_in_booking_details_controller.dart index 994420c..9332e76 100644 --- a/lib/controllers/dine_in_booking_details_controller.dart +++ b/lib/controllers/dine_in_booking_details_controller.dart @@ -1,5 +1,5 @@ import 'package:customer/models/dine_in_booking_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DineInBookingDetailsController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/dine_in_controller.dart b/lib/controllers/dine_in_controller.dart index b582900..57c6524 100644 --- a/lib/controllers/dine_in_controller.dart +++ b/lib/controllers/dine_in_controller.dart @@ -7,7 +7,7 @@ import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../models/banner_model.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DineInController extends GetxController { RxBool isLoading = true.obs; @@ -28,7 +28,8 @@ class DineInController extends GetxController { RxList popularRestaurantList = [].obs; RxList bannerBottomModel = [].obs; - Rx pageBottomController = PageController(viewportFraction: 0.877).obs; + Rx pageBottomController = + PageController(viewportFraction: 0.877).obs; RxInt currentBottomPage = 0.obs; RxList favouriteList = [].obs; @@ -37,7 +38,9 @@ class DineInController extends GetxController { isLoading.value = true; await getZone(); - FireStoreUtils.getAllNearestRestaurant(isDining: true).listen((event) async { + FireStoreUtils.getAllNearestRestaurant(isDining: true).listen(( + event, + ) async { newArrivalRestaurantList.clear(); allNearestRestaurant.clear(); popularRestaurantList.clear(); @@ -47,12 +50,21 @@ class DineInController extends GetxController { popularRestaurantList.addAll(event); popularRestaurantList.sort( - (a, b) => Constant.calculateReview(reviewCount: b.reviewsCount.toString(), reviewSum: b.reviewsSum.toString()) - .compareTo(Constant.calculateReview(reviewCount: a.reviewsCount.toString(), reviewSum: a.reviewsSum.toString())), + (a, b) => Constant.calculateReview( + reviewCount: b.reviewsCount.toString(), + reviewSum: b.reviewsSum.toString(), + ).compareTo( + Constant.calculateReview( + reviewCount: a.reviewsCount.toString(), + reviewSum: a.reviewsSum.toString(), + ), + ), ); newArrivalRestaurantList.sort( - (a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo((a.createdAt ?? Timestamp.now()).toDate()), + (a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo( + (a.createdAt ?? Timestamp.now()).toDate(), + ), ); }); @@ -61,23 +73,17 @@ class DineInController extends GetxController { } Future getCategory() async { - await FireStoreUtils.getHomeVendorCategory().then( - (value) { - vendorCategoryModel.value = value; - }, - ); + await FireStoreUtils.getHomeVendorCategory().then((value) { + vendorCategoryModel.value = value; + }); - await FireStoreUtils.getHomeBottomBanner().then( - (value) { - bannerBottomModel.value = value; - }, - ); + await FireStoreUtils.getHomeBottomBanner().then((value) { + bannerBottomModel.value = value; + }); if (Constant.userModel != null) { - await FireStoreUtils.getFavouriteRestaurant().then( - (value) { - favouriteList.value = value; - }, - ); + await FireStoreUtils.getFavouriteRestaurant().then((value) { + favouriteList.value = value; + }); } } @@ -85,7 +91,13 @@ class DineInController extends GetxController { await FireStoreUtils.getZone().then((value) { if (value != null) { for (int i = 0; i < value.length; i++) { - if (Constant.isPointInPolygon(LatLng(Constant.selectedLocation.location!.latitude ?? 0.0, Constant.selectedLocation.location!.longitude ?? 0.0), value[i].area!)) { + if (Constant.isPointInPolygon( + LatLng( + Constant.selectedLocation.location!.latitude ?? 0.0, + Constant.selectedLocation.location!.longitude ?? 0.0, + ), + value[i].area!, + )) { Constant.selectedZone = value[i]; Constant.isZoneAvailable = true; break; @@ -96,5 +108,4 @@ class DineInController extends GetxController { } }); } - } diff --git a/lib/controllers/dine_in_restaurant_details_controller.dart b/lib/controllers/dine_in_restaurant_details_controller.dart index 8d2105c..5436203 100644 --- a/lib/controllers/dine_in_restaurant_details_controller.dart +++ b/lib/controllers/dine_in_restaurant_details_controller.dart @@ -8,16 +8,18 @@ import 'package:easy_localization/easy_localization.dart'; import '../screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_screen.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../service/send_notification.dart'; import '../themes/show_toast_dialog.dart'; class DineInRestaurantDetailsController extends GetxController { - Rx searchEditingController = TextEditingController().obs; + Rx searchEditingController = + TextEditingController().obs; - Rx additionRequestController = TextEditingController().obs; + Rx additionRequestController = + TextEditingController().obs; RxBool isLoading = true.obs; RxBool firstVisit = false.obs; @@ -42,6 +44,7 @@ class DineInRestaurantDetailsController extends GetxController { return key; } } + RxString selectedOccasion = "".obs; RxList dateList = [].obs; @@ -65,30 +68,53 @@ class DineInRestaurantDetailsController extends GetxController { ShowToastDialog.showLoader("Please wait...".tr()); DateTime dt = selectedDate.value.toDate(); - String hour = DateFormat("kk:mm").format(DateFormat('hh:mm a').parse((Intl.getCurrentLocale() == "en_US") ? selectedTimeSlot.value : selectedTimeSlot.value.toLowerCase())); - dt = DateTime(dt.year, dt.month, dt.day, int.parse(hour.split(":")[0]), int.parse(hour.split(":")[1]), dt.second, dt.millisecond, dt.microsecond); + String hour = DateFormat("kk:mm").format( + DateFormat('hh:mm a').parse( + (Intl.getCurrentLocale() == "en_US") + ? selectedTimeSlot.value + : selectedTimeSlot.value.toLowerCase(), + ), + ); + dt = DateTime( + dt.year, + dt.month, + dt.day, + int.parse(hour.split(":")[0]), + int.parse(hour.split(":")[1]), + dt.second, + dt.millisecond, + dt.microsecond, + ); selectedDate.value = Timestamp.fromDate(dt); DineInBookingModel dineInBookingModel = DineInBookingModel( - id: Constant.getUuid(), - author: Constant.userModel, - authorID: FireStoreUtils.getCurrentUid(), - createdAt: Timestamp.now(), - date: selectedDate.value, - status: Constant.orderPlaced, - vendor: vendorModel.value, - specialRequest: additionRequestController.value.text.isEmpty ? "" : additionRequestController.value.text, - vendorID: vendorModel.value.id, - guestEmail: Constant.userModel!.email, - guestFirstName: Constant.userModel!.firstName, - guestLastName: Constant.userModel!.lastName, - guestPhone: Constant.userModel!.phoneNumber, - occasion: selectedOccasion.value, - discount: selectedTimeDiscount.value, - discountType: selectedTimeDiscountType.value, - totalGuest: noOfQuantity.value.toString(), - firstVisit: firstVisit.value); + id: Constant.getUuid(), + author: Constant.userModel, + authorID: FireStoreUtils.getCurrentUid(), + createdAt: Timestamp.now(), + date: selectedDate.value, + status: Constant.orderPlaced, + vendor: vendorModel.value, + specialRequest: + additionRequestController.value.text.isEmpty + ? "" + : additionRequestController.value.text, + vendorID: vendorModel.value.id, + guestEmail: Constant.userModel!.email, + guestFirstName: Constant.userModel!.firstName, + guestLastName: Constant.userModel!.lastName, + guestPhone: Constant.userModel!.phoneNumber, + occasion: selectedOccasion.value, + discount: selectedTimeDiscount.value, + discountType: selectedTimeDiscountType.value, + totalGuest: noOfQuantity.value.toString(), + firstVisit: firstVisit.value, + ); await FireStoreUtils.setBookedOrder(dineInBookingModel); - await SendNotification.sendFcmMessage(Constant.dineInPlaced, vendorModel.value.fcmToken.toString(), {}); + await SendNotification.sendFcmMessage( + Constant.dineInPlaced, + vendorModel.value.fcmToken.toString(), + {}, + ); ShowToastDialog.closeLoader(); Get.back(); Get.to(const DineInBookingScreen()); @@ -99,27 +125,46 @@ class DineInRestaurantDetailsController extends GetxController { for (int i = 0; i < 7; i++) { final now = DateTime.now().add(Duration(days: i)); var day = DateFormat('EEEE').format(now); - if (vendorModel.value.specialDiscount?.isNotEmpty == true && vendorModel.value.specialDiscountEnable == true) { + if (vendorModel.value.specialDiscount?.isNotEmpty == true && + vendorModel.value.specialDiscountEnable == true) { for (var element in vendorModel.value.specialDiscount!) { if (day == element.day.toString()) { if (element.timeslot!.isNotEmpty) { - SpecialDiscountTimeslot employeeWithMaxSalary = - element.timeslot!.reduce((item1, item2) => double.parse(item1.discount.toString()) > double.parse(item2.discount.toString()) ? item1 : item2); + SpecialDiscountTimeslot employeeWithMaxSalary = element.timeslot! + .reduce( + (item1, item2) => + double.parse(item1.discount.toString()) > + double.parse(item2.discount.toString()) + ? item1 + : item2, + ); if (employeeWithMaxSalary.discountType == "dinein") { - DateModel model = DateModel(date: Timestamp.fromDate(now), discountPer: employeeWithMaxSalary.discount.toString()); + DateModel model = DateModel( + date: Timestamp.fromDate(now), + discountPer: employeeWithMaxSalary.discount.toString(), + ); dateList.add(model); } else { - DateModel model = DateModel(date: Timestamp.fromDate(now), discountPer: "0"); + DateModel model = DateModel( + date: Timestamp.fromDate(now), + discountPer: "0", + ); dateList.add(model); } } else { - DateModel model = DateModel(date: Timestamp.fromDate(now), discountPer: "0"); + DateModel model = DateModel( + date: Timestamp.fromDate(now), + discountPer: "0", + ); dateList.add(model); } } } } else { - DateModel model = DateModel(date: Timestamp.fromDate(now), discountPer: "0"); + DateModel model = DateModel( + date: Timestamp.fromDate(now), + discountPer: "0", + ); dateList.add(model); } } @@ -127,70 +172,116 @@ class DineInRestaurantDetailsController extends GetxController { timeSet(selectedDate.value); if (timeSlotList.isNotEmpty) { - selectedTimeSlot.value = DateFormat('hh:mm a').format(timeSlotList[0].time!); + selectedTimeSlot.value = DateFormat( + 'hh:mm a', + ).format(timeSlotList[0].time!); } } void timeSet(Timestamp selectedDate) { timeSlotList.clear(); - for (DateTime time = Constant.stringToDate(vendorModel.value.openDineTime.toString()); - time.isBefore(Constant.stringToDate(vendorModel.value.closeDineTime.toString())); - time = time.add(const Duration(minutes: 30))) { + for ( + DateTime time = Constant.stringToDate( + vendorModel.value.openDineTime.toString(), + ); + time.isBefore( + Constant.stringToDate(vendorModel.value.closeDineTime.toString()), + ); + time = time.add(const Duration(minutes: 30)) + ) { final now = DateTime.parse(selectedDate.toDate().toString()); var day = DateFormat('EEEE').format(now); var date = DateFormat('dd-MM-yyyy').format(now); - if (vendorModel.value.specialDiscount?.isNotEmpty == true && vendorModel.value.specialDiscountEnable == true) { + if (vendorModel.value.specialDiscount?.isNotEmpty == true && + vendorModel.value.specialDiscountEnable == true) { for (var element in vendorModel.value.specialDiscount!) { if (day == element.day.toString()) { if (element.timeslot!.isNotEmpty) { for (var element in element.timeslot!) { if (element.discountType == "dinein") { - var start = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.from}"); - var end = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.to}"); - var selected = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${DateFormat.Hm().format(time)}"); + var start = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.from}"); + var end = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.to}"); + var selected = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${DateFormat.Hm().format(time)}"); if (isCurrentDateInRangeDineIn(start, end, selected)) { - var contains = timeSlotList.where((element) => element.time == time); + var contains = timeSlotList.where( + (element) => element.time == time, + ); if (contains.isNotEmpty) { - var index = timeSlotList.indexWhere((element) => element.time == time); + var index = timeSlotList.indexWhere( + (element) => element.time == time, + ); if (timeSlotList[index].discountPer == "0") { timeSlotList.removeAt(index); - TimeModel model = TimeModel(time: time, discountPer: element.discount, discountType: element.type); + TimeModel model = TimeModel( + time: time, + discountPer: element.discount, + discountType: element.type, + ); timeSlotList.insert(index == 0 ? 0 : index, model); } } else { - TimeModel model = TimeModel(time: time, discountPer: element.discount, discountType: element.type); + TimeModel model = TimeModel( + time: time, + discountPer: element.discount, + discountType: element.type, + ); timeSlotList.add(model); } } else { - var contains = timeSlotList.where((element) => element.time == time); + var contains = timeSlotList.where( + (element) => element.time == time, + ); if (contains.isEmpty) { - TimeModel model = TimeModel(time: time, discountPer: "0", discountType: "amount"); + TimeModel model = TimeModel( + time: time, + discountPer: "0", + discountType: "amount", + ); timeSlotList.add(model); } } } else { - TimeModel model = TimeModel(time: time, discountPer: "0", discountType: "amount"); + TimeModel model = TimeModel( + time: time, + discountPer: "0", + discountType: "amount", + ); timeSlotList.add(model); } } } else { - TimeModel model = TimeModel(time: time, discountPer: "0", discountType: "amount"); + TimeModel model = TimeModel( + time: time, + discountPer: "0", + discountType: "amount", + ); timeSlotList.add(model); } } } } else { - TimeModel model = TimeModel(time: time, discountPer: "0", discountType: "amount"); + TimeModel model = TimeModel( + time: time, + discountPer: "0", + discountType: "amount", + ); timeSlotList.add(model); } } } void animateSlider() { - if (vendorModel.value.photos != null && vendorModel.value.photos!.isNotEmpty) { + if (vendorModel.value.photos != null && + vendorModel.value.photos!.isNotEmpty) { Timer.periodic(const Duration(seconds: 2), (Timer timer) { if (currentPage < vendorModel.value.photos!.length) { currentPage++; @@ -226,18 +317,16 @@ class DineInRestaurantDetailsController extends GetxController { Future getFavouriteList() async { if (Constant.userModel != null) { - await FireStoreUtils.getFavouriteRestaurant().then( - (value) { - favouriteList.value = value; - }, - ); + await FireStoreUtils.getFavouriteRestaurant().then((value) { + favouriteList.value = value; + }); } - await FireStoreUtils.getVendorCuisines(vendorModel.value.id.toString()).then( - (value) { - tags.value = value; - }, - ); + await FireStoreUtils.getVendorCuisines( + vendorModel.value.id.toString(), + ).then((value) { + tags.value = value; + }); update(); } @@ -251,8 +340,12 @@ class DineInRestaurantDetailsController extends GetxController { if (day == element.day.toString()) { if (element.timeslot!.isNotEmpty) { for (var element in element.timeslot!) { - var start = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.from}"); - var end = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.to}"); + var start = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.from}"); + var end = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.to}"); if (isCurrentDateInRange(start, end)) { isOpen.value = true; } @@ -262,8 +355,14 @@ class DineInRestaurantDetailsController extends GetxController { } } - bool isCurrentDateInRangeDineIn(DateTime startDate, DateTime endDate, DateTime selected) { - return selected.isAtSameMomentAs(startDate) || selected.isAtSameMomentAs(endDate) || selected.isAfter(startDate) && selected.isBefore(endDate); + bool isCurrentDateInRangeDineIn( + DateTime startDate, + DateTime endDate, + DateTime selected, + ) { + return selected.isAtSameMomentAs(startDate) || + selected.isAtSameMomentAs(endDate) || + selected.isAfter(startDate) && selected.isBefore(endDate); } bool isCurrentDateInRange(DateTime startDate, DateTime endDate) { @@ -284,5 +383,9 @@ class TimeModel { String? discountPer; String? discountType; - TimeModel({required this.time, required this.discountPer, required this.discountType}); + TimeModel({ + required this.time, + required this.discountPer, + required this.discountType, + }); } diff --git a/lib/controllers/discount_restaurant_list_controller.dart b/lib/controllers/discount_restaurant_list_controller.dart index 4b01083..bc5b12e 100644 --- a/lib/controllers/discount_restaurant_list_controller.dart +++ b/lib/controllers/discount_restaurant_list_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/models/vendor_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class DiscountRestaurantListController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/edit_profile_controller.dart b/lib/controllers/edit_profile_controller.dart index 47537b4..6fc4203 100644 --- a/lib/controllers/edit_profile_controller.dart +++ b/lib/controllers/edit_profile_controller.dart @@ -5,7 +5,7 @@ import 'package:easy_localization/easy_localization.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:image_picker/image_picker.dart'; import '../themes/show_toast_dialog.dart'; @@ -18,7 +18,8 @@ class EditProfileController extends GetxController { Rx lastNameController = TextEditingController().obs; Rx emailController = TextEditingController().obs; Rx phoneNumberController = TextEditingController().obs; - Rx countryCodeController = TextEditingController(text: "+91").obs; + Rx countryCodeController = + TextEditingController(text: "+91").obs; @override void onInit() { @@ -27,14 +28,18 @@ class EditProfileController extends GetxController { } Future getData() async { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { if (value != null) { userModel.value = value; firstNameController.value.text = userModel.value.firstName.toString(); lastNameController.value.text = userModel.value.lastName.toString(); emailController.value.text = userModel.value.email.toString(); - phoneNumberController.value.text = userModel.value.phoneNumber.toString(); - countryCodeController.value.text = userModel.value.countryCode.toString(); + phoneNumberController.value.text = + userModel.value.phoneNumber.toString(); + countryCodeController.value.text = + userModel.value.countryCode.toString(); profileImage.value = userModel.value.profilePictureURL ?? ""; } }); @@ -44,7 +49,8 @@ class EditProfileController extends GetxController { Future saveData() async { ShowToastDialog.showLoader("Please wait...".tr()); - if (Constant().hasValidUrl(profileImage.value) == false && profileImage.value.isNotEmpty) { + if (Constant().hasValidUrl(profileImage.value) == false && + profileImage.value.isNotEmpty) { profileImage.value = await Constant.uploadUserImageToFireStorage( File(profileImage.value), "profileImage/${FireStoreUtils.getCurrentUid()}", diff --git a/lib/controllers/enter_manually_location_controller.dart b/lib/controllers/enter_manually_location_controller.dart index a3962f1..6a7382d 100644 --- a/lib/controllers/enter_manually_location_controller.dart +++ b/lib/controllers/enter_manually_location_controller.dart @@ -1,8 +1,7 @@ import 'package:customer/service/fire_store_utils.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../models/user_model.dart'; class EnterManuallyLocationController extends GetxController { @@ -13,9 +12,12 @@ class EnterManuallyLocationController extends GetxController { List saveAsList = ['Home', 'Work', 'Hotel', 'other'].obs; RxString selectedSaveAs = "Home".obs; - Rx houseBuildingTextEditingController = TextEditingController().obs; - Rx localityEditingController = TextEditingController().obs; - Rx landmarkEditingController = TextEditingController().obs; + Rx houseBuildingTextEditingController = + TextEditingController().obs; + Rx localityEditingController = + TextEditingController().obs; + Rx landmarkEditingController = + TextEditingController().obs; Rx location = UserLocation().obs; Rx shippingModel = ShippingAddress().obs; RxBool isLoading = false.obs; @@ -36,7 +38,8 @@ class EnterManuallyLocationController extends GetxController { mode.value = argumentData['mode'] ?? "Add"; //check address - if (argumentData['address'] != null && argumentData['address'] is ShippingAddress) { + if (argumentData['address'] != null && + argumentData['address'] is ShippingAddress) { shippingModel.value = argumentData['address']; setData(shippingModel.value); } @@ -49,7 +52,8 @@ class EnterManuallyLocationController extends GetxController { void setData(ShippingAddress shippingAddress) { shippingModel.value = shippingAddress; - houseBuildingTextEditingController.value.text = shippingAddress.address.toString(); + houseBuildingTextEditingController.value.text = + shippingAddress.address.toString(); localityEditingController.value.text = shippingAddress.locality.toString(); landmarkEditingController.value.text = shippingAddress.landmark.toString(); selectedSaveAs.value = shippingAddress.addressAs.toString(); @@ -57,7 +61,9 @@ class EnterManuallyLocationController extends GetxController { } Future getUser() async { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { if (value != null) { userModel.value = value; if (userModel.value.shippingAddress != null) { diff --git a/lib/controllers/favourite_controller.dart b/lib/controllers/favourite_controller.dart index 149265e..b150298 100644 --- a/lib/controllers/favourite_controller.dart +++ b/lib/controllers/favourite_controller.dart @@ -5,7 +5,7 @@ import 'package:customer/models/favourite_model.dart'; import 'package:customer/models/product_model.dart'; import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class FavouriteController extends GetxController { RxBool favouriteRestaurant = true.obs; @@ -35,14 +35,22 @@ class FavouriteController extends GetxController { }); for (var element in favouriteList) { - await FireStoreUtils.getVendorById(element.restaurantId.toString()).then((value) async { + await FireStoreUtils.getVendorById( + element.restaurantId.toString(), + ).then((value) async { if (value != null) { - if ((Constant.isSubscriptionModelApplied == true || value.adminCommission?.isEnabled == true) && value.subscriptionPlan != null) { + if ((Constant.isSubscriptionModelApplied == true || + value.adminCommission?.isEnabled == true) && + value.subscriptionPlan != null) { if (value.subscriptionTotalOrders == "-1") { favouriteVendorList.add(value); } else { print("Restaurant :: ${value.title.toString()}"); - if ((value.subscriptionExpiryDate != null && value.subscriptionExpiryDate!.toDate().isBefore(DateTime.now()) == false) || + if ((value.subscriptionExpiryDate != null && + value.subscriptionExpiryDate!.toDate().isBefore( + DateTime.now(), + ) == + false) || value.subscriptionPlan?.expiryDay == '-1') { if (value.subscriptionTotalOrders != '0') { favouriteVendorList.add(value); @@ -57,32 +65,45 @@ class FavouriteController extends GetxController { } for (var element in favouriteItemList) { - await FireStoreUtils.getProductById(element.productId.toString()).then((value) async { + await FireStoreUtils.getProductById(element.productId.toString()).then(( + value, + ) async { if (value != null) { - await FireStoreUtils.fireStore.collection(CollectionName.vendors).doc(value.vendorID.toString()).get().then((value1) async { - if (value1.exists) { - VendorModel vendorModel = VendorModel.fromJson(value1.data()!); - if(value.publish == true){ - if (Constant.isSubscriptionModelApplied == true || vendorModel.adminCommission?.isEnabled == true) { - if (vendorModel.subscriptionPlan != null) { - if (vendorModel.subscriptionTotalOrders == "-1") { - favouriteFoodList.add(value); - } else { - if ((vendorModel.subscriptionExpiryDate != null && vendorModel.subscriptionExpiryDate!.toDate().isBefore(DateTime.now()) == false) || - vendorModel.subscriptionPlan?.expiryDay == "-1") { - if (vendorModel.subscriptionTotalOrders != '0') { + await FireStoreUtils.fireStore + .collection(CollectionName.vendors) + .doc(value.vendorID.toString()) + .get() + .then((value1) async { + if (value1.exists) { + VendorModel vendorModel = VendorModel.fromJson( + value1.data()!, + ); + if (value.publish == true) { + if (Constant.isSubscriptionModelApplied == true || + vendorModel.adminCommission?.isEnabled == true) { + if (vendorModel.subscriptionPlan != null) { + if (vendorModel.subscriptionTotalOrders == "-1") { favouriteFoodList.add(value); + } else { + if ((vendorModel.subscriptionExpiryDate != null && + vendorModel.subscriptionExpiryDate! + .toDate() + .isBefore(DateTime.now()) == + false) || + vendorModel.subscriptionPlan?.expiryDay == + "-1") { + if (vendorModel.subscriptionTotalOrders != '0') { + favouriteFoodList.add(value); + } + } } } + } else { + favouriteFoodList.add(value); } } - } else { - favouriteFoodList.add(value); } - } - - } - }); + }); } }); } diff --git a/lib/controllers/favourite_ondemmand_controller.dart b/lib/controllers/favourite_ondemmand_controller.dart index 0ed8f26..19174cf 100644 --- a/lib/controllers/favourite_ondemmand_controller.dart +++ b/lib/controllers/favourite_ondemmand_controller.dart @@ -4,13 +4,14 @@ import 'package:customer/models/favorite_ondemand_service_model.dart'; import 'package:customer/models/provider_serivce_model.dart'; import 'package:customer/screen_ui/auth_screens/login_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class FavouriteOndemmandController extends GetxController { // Add your controller logic here Rx isLoading = false.obs; - RxList lstFav = [].obs; + RxList lstFav = + [].obs; RxList categories = [].obs; @override @@ -25,7 +26,9 @@ class FavouriteOndemmandController extends GetxController { await FireStoreUtils.getOnDemandCategory().then((catValue) { categories.value = catValue; }); - await FireStoreUtils.getFavouritesServiceList(FireStoreUtils.getCurrentUid()).then((favList) { + await FireStoreUtils.getFavouritesServiceList( + FireStoreUtils.getCurrentUid(), + ).then((favList) { lstFav.value = favList; }); isLoading.value = false; @@ -35,23 +38,27 @@ class FavouriteOndemmandController extends GetxController { if (Constant.userModel == null) { Get.to(LoginScreen()); } else { - var contain = lstFav.where((element) => element.service_id == provider.id); + var contain = lstFav.where( + (element) => element.service_id == provider.id, + ); if (contain.isNotEmpty) { - FavouriteOndemandServiceModel favouriteModel = FavouriteOndemandServiceModel( - section_id: provider.sectionId, - service_id: provider.id, - user_id: FireStoreUtils.getCurrentUid(), - serviceAuthorId: provider.author, - ); + FavouriteOndemandServiceModel favouriteModel = + FavouriteOndemandServiceModel( + section_id: provider.sectionId, + service_id: provider.id, + user_id: FireStoreUtils.getCurrentUid(), + serviceAuthorId: provider.author, + ); FireStoreUtils.removeFavouriteOndemandService(favouriteModel); lstFav.removeWhere((item) => item.service_id == provider.id); } else { - FavouriteOndemandServiceModel favouriteModel = FavouriteOndemandServiceModel( - section_id: provider.sectionId, - service_id: provider.id, - user_id: FireStoreUtils.getCurrentUid(), - serviceAuthorId: provider.author, - ); + FavouriteOndemandServiceModel favouriteModel = + FavouriteOndemandServiceModel( + section_id: provider.sectionId, + service_id: provider.id, + user_id: FireStoreUtils.getCurrentUid(), + serviceAuthorId: provider.author, + ); FireStoreUtils.setFavouriteOndemandSection(favouriteModel); lstFav.add(favouriteModel); } @@ -63,7 +70,9 @@ class FavouriteOndemmandController extends GetxController { if (categoryId == null || categoryId.isEmpty) return null; // Try to find category from cached list - CategoryModel? cat = categories.firstWhereOrNull((element) => element.id == categoryId); + CategoryModel? cat = categories.firstWhereOrNull( + (element) => element.id == categoryId, + ); // If not found, fetch from Firestore cat ??= await FireStoreUtils.getCategoryById(categoryId); diff --git a/lib/controllers/food_home_controller.dart b/lib/controllers/food_home_controller.dart index 3e1a300..2ffdf08 100644 --- a/lib/controllers/food_home_controller.dart +++ b/lib/controllers/food_home_controller.dart @@ -11,7 +11,7 @@ import 'package:customer/models/vendor_model.dart'; import 'package:customer/utils/preferences.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../models/banner_model.dart'; import '../models/story_model.dart'; @@ -35,8 +35,10 @@ class FoodHomeController extends GetxController { RxBool isPopular = true.obs; RxString selectedOrderTypeValue = "Delivery".tr().obs; - Rx pageController = PageController(viewportFraction: 0.877).obs; - Rx pageBottomController = PageController(viewportFraction: 0.877).obs; + Rx pageController = + PageController(viewportFraction: 0.877).obs; + Rx pageBottomController = + PageController(viewportFraction: 0.877).obs; RxInt currentPage = 0.obs; RxInt currentBottomPage = 0.obs; @@ -66,7 +68,10 @@ class FoodHomeController extends GetxController { Future getData() async { isLoading.value = true; getCartData(); - selectedOrderTypeValue.value = Preferences.getString(Preferences.foodDeliveryType, defaultValue: "Delivery"); + selectedOrderTypeValue.value = Preferences.getString( + Preferences.foodDeliveryType, + defaultValue: "Delivery", + ); await getZone(); FireStoreUtils.getAllNearestRestaurant().listen((event) async { popularRestaurantList.clear(); @@ -82,17 +87,27 @@ class FoodHomeController extends GetxController { (a, b) => Constant.calculateReview( reviewCount: b.reviewsCount.toString(), reviewSum: b.reviewsSum.toString(), - ).compareTo(Constant.calculateReview(reviewCount: a.reviewsCount.toString(), reviewSum: a.reviewsSum.toString())), + ).compareTo( + Constant.calculateReview( + reviewCount: a.reviewsCount.toString(), + reviewSum: a.reviewsSum.toString(), + ), + ), ); - newArrivalRestaurantList.sort((a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo((a.createdAt ?? Timestamp.now()).toDate())); + newArrivalRestaurantList.sort( + (a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo( + (a.createdAt ?? Timestamp.now()).toDate(), + ), + ); await getVendorCategory(); await FireStoreUtils.getHomeCoupon().then((value) { couponRestaurantList.clear(); couponList.clear(); for (var element1 in value) { for (var element in allNearestRestaurant) { - if (element1.vendorID == element.id && element1.expiresAt!.toDate().isAfter(DateTime.now())) { + if (element1.vendorID == element.id && + element1.expiresAt!.toDate().isAfter(DateTime.now())) { couponList.add(element1); couponRestaurantList.add(element); } @@ -110,7 +125,7 @@ class FoodHomeController extends GetxController { print("nearestIds: $nearestIds"); // Filter stories whose vendorID exists in nearestIds storyList.addAll( - stories.where((story) => nearestIds.contains(story.vendorID)) + stories.where((story) => nearestIds.contains(story.vendorID)), ); print("Filtered storyList length: ${storyList.length}"); }); @@ -148,8 +163,16 @@ class FoodHomeController extends GetxController { await FireStoreUtils.getHomeVendorCategory().then((value) { vendorCategoryModel.value = value; if (Constant.restaurantList != null) { - List usedCategoryIds = Constant.restaurantList!.expand((vendor) => vendor.categoryID ?? []).whereType().toSet().toList(); - vendorCategoryModel.value = vendorCategoryModel.where((category) => usedCategoryIds.contains(category.id)).toList(); + List usedCategoryIds = + Constant.restaurantList! + .expand((vendor) => vendor.categoryID ?? []) + .whereType() + .toSet() + .toList(); + vendorCategoryModel.value = + vendorCategoryModel + .where((category) => usedCategoryIds.contains(category.id)) + .toList(); } }); @@ -177,7 +200,13 @@ class FoodHomeController extends GetxController { await FireStoreUtils.getZone().then((value) { if (value != null) { for (int i = 0; i < value.length; i++) { - if (Constant.isPointInPolygon(LatLng(Constant.selectedLocation.location?.latitude ?? 0.0, Constant.selectedLocation.location?.longitude ?? 0.0), value[i].area!)) { + if (Constant.isPointInPolygon( + LatLng( + Constant.selectedLocation.location?.latitude ?? 0.0, + Constant.selectedLocation.location?.longitude ?? 0.0, + ), + value[i].area!, + )) { Constant.selectedZone = value[i]; Constant.isZoneAvailable = true; break; diff --git a/lib/controllers/forgot_password_controller.dart b/lib/controllers/forgot_password_controller.dart index 0ea2da8..4b84ad8 100644 --- a/lib/controllers/forgot_password_controller.dart +++ b/lib/controllers/forgot_password_controller.dart @@ -1,7 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../themes/show_toast_dialog.dart'; class ForgotPasswordController extends GetxController { @@ -26,7 +26,8 @@ class ForgotPasswordController extends GetxController { await FirebaseAuth.instance.sendPasswordResetEmail(email: email); ShowToastDialog.closeLoader(); ShowToastDialog.showToast( - 'reset_password_link_sent'.trParams({'email': email}), + 'reset_password_link_sent'.tr(namedArgs: {'email': email}) + ); Get.back(); } on FirebaseAuthException catch (e) { @@ -34,7 +35,9 @@ class ForgotPasswordController extends GetxController { if (e.code == 'user-not-found') { ShowToastDialog.showToast('No user found for that email.'.tr()); } else { - ShowToastDialog.showToast(e.message?.tr() ?? "something_went_wrong".tr()); + ShowToastDialog.showToast( + e.message?.tr() ?? "something_went_wrong".tr(), + ); } } } diff --git a/lib/controllers/gift_card_controller.dart b/lib/controllers/gift_card_controller.dart index 3476e93..0acedfe 100644 --- a/lib/controllers/gift_card_controller.dart +++ b/lib/controllers/gift_card_controller.dart @@ -42,7 +42,7 @@ import '../screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import '../service/fire_store_utils.dart'; import 'package:customer/utils/preferences.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:uuid/uuid.dart'; @@ -76,27 +76,31 @@ class GiftCardController extends GetxController { giftCardList = value; if (giftCardList.isNotEmpty) { selectedGiftCard.value = giftCardList.first; - messageController.value.text = selectedGiftCard.value.message.toString(); + messageController.value.text = + selectedGiftCard.value.message.toString(); } }); isLoading.value = false; - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then( - (value) { - if (value != null) { - userModel.value = value; - } - }, - ); + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { + if (value != null) { + userModel.value = value; + } + }); await getPaymentSettings(); } Future placeOrder() async { if (selectedPaymentMethod.value == PaymentGateway.wallet.name) { - if (double.parse(userModel.value.walletAmount.toString()) >= double.parse(amountController.value.text)) { + if (double.parse(userModel.value.walletAmount.toString()) >= + double.parse(amountController.value.text)) { setOrder(); } else { - ShowToastDialog.showToast("You don't have sufficient wallet balance to purchase gift card".tr()); + ShowToastDialog.showToast( + "You don't have sufficient wallet balance to purchase gift card".tr(), + ); } } else { setOrder(); @@ -116,26 +120,34 @@ class GiftCardController extends GetxController { giftCardsOrderModel.giftCode = generateGiftCode(); giftCardsOrderModel.paymentType = selectedPaymentMethod.value; giftCardsOrderModel.createdDate = Timestamp.now(); - DateTime dateTime = DateTime.now().add(Duration(days: int.parse(selectedGiftCard.value.expiryDay ?? "2"))); + DateTime dateTime = DateTime.now().add( + Duration(days: int.parse(selectedGiftCard.value.expiryDay ?? "2")), + ); giftCardsOrderModel.expireDate = Timestamp.fromDate(dateTime); giftCardsOrderModel.userid = FireStoreUtils.getCurrentUid(); if (selectedPaymentMethod.value == PaymentGateway.wallet.name) { WalletTransactionModel transactionModel = WalletTransactionModel( - id: Constant.getUuid(), - amount: double.parse(amountController.value.text), - date: Timestamp.now(), - paymentMethod: PaymentGateway.wallet.name, - transactionUser: "user", - userId: FireStoreUtils.getCurrentUid(), - isTopup: false, - orderId: giftCardsOrderModel.id, - note: "Gift card purchase amount debited".tr(), - paymentStatus: "success".tr()); + id: Constant.getUuid(), + amount: double.parse(amountController.value.text), + date: Timestamp.now(), + paymentMethod: PaymentGateway.wallet.name, + transactionUser: "user", + userId: FireStoreUtils.getCurrentUid(), + isTopup: false, + orderId: giftCardsOrderModel.id, + note: "Gift card purchase amount debited".tr(), + paymentStatus: "success".tr(), + ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${amountController.value.text.toString()}", userId: FireStoreUtils.getCurrentUid()).then((value) {}); + await FireStoreUtils.updateUserWallet( + amount: "-${amountController.value.text.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ).then((value) {}); } }); } @@ -179,54 +191,78 @@ class GiftCardController extends GetxController { Rx xenditModel = Xendit().obs; Future getPaymentSettings() async { - await FireStoreUtils.getPaymentSettingsData().then( - (value) { - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - if (walletSettingModel.value.isEnabled == true) { - selectedPaymentMethod.value = PaymentGateway.wallet.name; - } else if (stripeModel.value.isEnabled == true) { - selectedPaymentMethod.value = PaymentGateway.stripe.name; - } else if (payPalModel.value.isEnabled == true) { - selectedPaymentMethod.value = PaymentGateway.paypal.name; - } else if (payStackModel.value.isEnable == true) { - selectedPaymentMethod.value = PaymentGateway.payStack.name; - } else if (mercadoPagoModel.value.isEnabled == true) { - selectedPaymentMethod.value = PaymentGateway.mercadoPago.name; - } else if (flutterWaveModel.value.isEnable == true) { - selectedPaymentMethod.value = PaymentGateway.flutterWave.name; - }else if (payFastModel.value.isEnable == true) { - selectedPaymentMethod.value = PaymentGateway.payFast.name; - } else if (razorPayModel.value.isEnabled == true) { - selectedPaymentMethod.value = PaymentGateway.razorpay.name; - } else if (midTransModel.value.enable == true) { - selectedPaymentMethod.value = PaymentGateway.midTrans.name; - } else if (orangeMoneyModel.value.enable == true) { - selectedPaymentMethod.value = PaymentGateway.orangeMoney.name; - } else if (xenditModel.value.enable == true) { - selectedPaymentMethod.value = PaymentGateway.xendit.name; - } - Stripe.publishableKey = stripeModel.value.clientpublishableKey.toString(); - Stripe.merchantIdentifier = 'GoRide'; - Stripe.instance.applySettings(); - setRef(); + await FireStoreUtils.getPaymentSettingsData().then((value) { + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + if (walletSettingModel.value.isEnabled == true) { + selectedPaymentMethod.value = PaymentGateway.wallet.name; + } else if (stripeModel.value.isEnabled == true) { + selectedPaymentMethod.value = PaymentGateway.stripe.name; + } else if (payPalModel.value.isEnabled == true) { + selectedPaymentMethod.value = PaymentGateway.paypal.name; + } else if (payStackModel.value.isEnable == true) { + selectedPaymentMethod.value = PaymentGateway.payStack.name; + } else if (mercadoPagoModel.value.isEnabled == true) { + selectedPaymentMethod.value = PaymentGateway.mercadoPago.name; + } else if (flutterWaveModel.value.isEnable == true) { + selectedPaymentMethod.value = PaymentGateway.flutterWave.name; + } else if (payFastModel.value.isEnable == true) { + selectedPaymentMethod.value = PaymentGateway.payFast.name; + } else if (razorPayModel.value.isEnabled == true) { + selectedPaymentMethod.value = PaymentGateway.razorpay.name; + } else if (midTransModel.value.enable == true) { + selectedPaymentMethod.value = PaymentGateway.midTrans.name; + } else if (orangeMoneyModel.value.enable == true) { + selectedPaymentMethod.value = PaymentGateway.orangeMoney.name; + } else if (xenditModel.value.enable == true) { + selectedPaymentMethod.value = PaymentGateway.xendit.name; + } + Stripe.publishableKey = stripeModel.value.clientpublishableKey.toString(); + Stripe.merchantIdentifier = 'GoRide'; + Stripe.instance.applySettings(); + setRef(); - razorPay.on(Razorpay.EVENT_PAYMENT_SUCCESS, handlePaymentSuccess); - razorPay.on(Razorpay.EVENT_EXTERNAL_WALLET, handleExternalWaller); - razorPay.on(Razorpay.EVENT_PAYMENT_ERROR, handlePaymentError); - }, - ); + razorPay.on(Razorpay.EVENT_PAYMENT_SUCCESS, handlePaymentSuccess); + razorPay.on(Razorpay.EVENT_EXTERNAL_WALLET, handleExternalWaller); + razorPay.on(Razorpay.EVENT_PAYMENT_ERROR, handlePaymentError); + }); } // final _flutterPaypalNativePlugin = FlutterPaypalNative.instance; @@ -297,28 +333,34 @@ class GiftCardController extends GetxController { // Strip Future stripeMakePayment({required String amount}) async { try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin."); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.", + ); } else { await Stripe.instance.initPaymentSheet( - paymentSheetParameters: SetupPaymentSheetParameters( - paymentIntentClientSecret: paymentIntentData['client_secret'], - allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay( - merchantCountryCode: 'US', - testEnv: true, - currencyCode: "USD", - ), - customFlow: true, - style: ThemeMode.system, - appearance: PaymentSheetAppearance( - colors: PaymentSheetAppearanceColors( - primary: AppThemeData.primary300, - ), - ), - merchantDisplayName: 'GoRide')); + paymentSheetParameters: SetupPaymentSheetParameters( + paymentIntentClientSecret: paymentIntentData['client_secret'], + allowsDelayedPaymentMethods: false, + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), + customFlow: true, + style: ThemeMode.system, + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), + merchantDisplayName: 'GoRide', + ), + ); displayStripePaymentSheet(amount: amount); } } catch (e, s) { @@ -357,8 +399,14 @@ class GiftCardController extends GetxController { "shipping[address][country]": "US", }; var stripeSecret = stripeModel.value.stripeSecret; - var response = await http.post(Uri.parse('https://api.stripe.com/v1/payment_intents'), - body: body, headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}); + var response = await http.post( + Uri.parse('https://api.stripe.com/v1/payment_intents'), + body: body, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + ); return jsonDecode(response.body); } catch (e) { @@ -367,7 +415,10 @@ class GiftCardController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { final headers = { 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json', @@ -381,7 +432,7 @@ class GiftCardController extends GetxController { "quantity": 1, "currency_id": "BRL", // or your preferred currency "unit_price": double.parse(amount), - } + }, ], "payer": {"email": userModel.value.email}, "back_urls": { @@ -389,7 +440,8 @@ class GiftCardController extends GetxController { "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success", }, - "auto_return": "approved" // Automatically return after payment is approved + "auto_return": + "approved", // Automatically return after payment is approved }); final response = await http.post( @@ -417,18 +469,22 @@ class GiftCardController extends GetxController { ///PayStack Payment Method Future payStackPayment(String totalAmount) async { await PayStackURLGen.payStackURLGen( - amount: (double.parse(totalAmount) * 100).toString(), currency: "ZAR", secretKey: payStackModel.value.secretKey.toString(), userModel: userModel.value) - .then((value) async { + amount: (double.parse(totalAmount) * 100).toString(), + currency: "ZAR", + secretKey: payStackModel.value.secretKey.toString(), + userModel: userModel.value, + ).then((value) async { if (value != null) { PayStackUrlModel payStackModel0 = value; - Get.to(PayStackScreen( - secretKey: payStackModel.value.secretKey.toString(), - callBackUrl: payStackModel.value.callbackURL.toString(), - initialURl: payStackModel0.data.authorizationUrl, - amount: totalAmount, - reference: payStackModel0.data.reference, - ))! - .then((value) { + Get.to( + PayStackScreen( + secretKey: payStackModel.value.secretKey.toString(), + callBackUrl: payStackModel.value.callbackURL.toString(), + initialURl: payStackModel0.data.authorizationUrl, + amount: totalAmount, + reference: payStackModel0.data.reference, + ), + )!.then((value) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -437,13 +493,18 @@ class GiftCardController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); final headers = { 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', @@ -464,14 +525,16 @@ class GiftCardController extends GetxController { "customizations": { "title": "Payment for Services", "description": "Payment for XYZ services", - } + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -500,8 +563,14 @@ class GiftCardController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: userModel.value).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: userModel.value, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -513,38 +582,40 @@ class GiftCardController extends GetxController { }); } -//PayPal + //PayPal void paypalPaymentSheet(String amount, context) { Navigator.of(context).push( MaterialPageRoute( - builder: (BuildContext context) => UsePaypal( - sandboxMode: payPalModel.value.isLive == true ? false : true, - clientId: payPalModel.value.paypalClient ?? '', - secretKey: payPalModel.value.paypalSecret ?? '', - returnURL: "com.parkme://paypalpay", - cancelURL: "com.parkme://paypalpay", - transactions: [ - { - "amount": { - "total": amount, - "currency": "USD", - "details": {"subtotal": amount} + builder: + (BuildContext context) => UsePaypal( + sandboxMode: payPalModel.value.isLive == true ? false : true, + clientId: payPalModel.value.paypalClient ?? '', + secretKey: payPalModel.value.paypalSecret ?? '', + returnURL: "com.parkme://paypalpay", + cancelURL: "com.parkme://paypalpay", + transactions: [ + { + "amount": { + "total": amount, + "currency": "USD", + "details": {"subtotal": amount}, + }, }, - } - ], - note: "Contact us for any questions on your order.", - onSuccess: (Map params) async { - placeOrder(); - ShowToastDialog.showToast("Payment Successful!!".tr()); - }, - onError: (error) { - Get.back(); - ShowToastDialog.showToast("Payment UnSuccessful!!".tr()); - }, - onCancel: (params) { - Get.back(); - ShowToastDialog.showToast("Payment UnSuccessful!!".tr()); - }), + ], + note: "Contact us for any questions on your order.", + onSuccess: (Map params) async { + placeOrder(); + ShowToastDialog.showToast("Payment Successful!!".tr()); + }, + onError: (error) { + Get.back(); + ShowToastDialog.showToast("Payment UnSuccessful!!".tr()); + }, + onCancel: (params) { + Get.back(); + ShowToastDialog.showToast("Payment UnSuccessful!!".tr()); + }, + ), ), ); } @@ -555,33 +626,52 @@ class GiftCardController extends GetxController { String getChecksum = "${Constant.globalUrl}payments/getpaytmchecksum"; final response = await http.post( - Uri.parse( - getChecksum, - ), - headers: {}, - body: { - "mid": paytmModel.value.paytmMID.toString(), - "order_id": orderId, - "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), - }); + Uri.parse(getChecksum), + headers: {}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + }, + ); final data = jsonDecode(response.body); - await verifyCheckSum(checkSum: data["code"], amount: amount, orderId: orderId).then((value) { + await verifyCheckSum( + checkSum: data["code"], + amount: amount, + orderId: orderId, + ).then((value) { initiatePayment(amount: amount, orderId: orderId).then((value) { String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } GetPaymentTxtTokenModel result = value; - startTransaction(context, txnTokenBy: result.body.txnToken ?? '', orderId: orderId, amount: amount, callBackURL: callback, isStaging: paytmModel.value.isSandboxEnabled); + startTransaction( + context, + txnTokenBy: result.body.txnToken ?? '', + orderId: orderId, + amount: amount, + callBackURL: callback, + isStaging: paytmModel.value.isSandboxEnabled, + ); }); }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -616,46 +706,61 @@ class GiftCardController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( - Uri.parse( - getChecksum, - ), - headers: {}, - body: { - "mid": paytmModel.value.paytmMID.toString(), - "order_id": orderId, - "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), - "checksum_value": checkSum, - }); + Uri.parse(getChecksum), + headers: {}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, + ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } - final response = await http.post(Uri.parse(initiateURL), headers: {}, body: { - "mid": paytmModel.value.paytmMID, - "order_id": orderId, - "key_secret": paytmModel.value.pAYTMMERCHANTKEY, - "amount": amount.toString(), - "currency": "INR", - "callback_url": callback, - "custId": FireStoreUtils.getCurrentUid(), - "issandbox": paytmModel.value.isSandboxEnabled == true ? "1" : "2", - }); + final response = await http.post( + Uri.parse(initiateURL), + headers: {}, + body: { + "mid": paytmModel.value.paytmMID, + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY, + "amount": amount.toString(), + "currency": "INR", + "callback_url": callback, + "custId": FireStoreUtils.getCurrentUid(), + "issandbox": paytmModel.value.isSandboxEnabled == true ? "1" : "2", + }, + ); print(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -678,8 +783,8 @@ class GiftCardController extends GetxController { 'email': userModel.value.email, }, 'external': { - 'wallets': ['paytm'] - } + 'wallets': ['paytm'], + }, }; try { @@ -706,14 +811,14 @@ class GiftCardController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { - Get.to(() => MidtransScreen( - initialURl: url, - ))! - .then((value) { + Get.to(() => MidtransScreen(initialURl: url))!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -727,14 +832,20 @@ class GiftCardController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!), + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), }, body: jsonEncode({ 'transaction_details': { @@ -742,7 +853,9 @@ class GiftCardController extends GetxController { 'gross_amount': double.parse(amount.toString()).toInt(), }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -750,7 +863,9 @@ class GiftCardController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -767,21 +882,30 @@ class GiftCardController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen( - initialURl: paymentURL, - accessToken: accessToken, - amount: amount, - orangePay: orangeMoneyModel.value, - orderId: orderId, - payToken: payToken, - ))! - .then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -793,19 +917,24 @@ class GiftCardController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; - Map requestBody = { - 'grant_type': 'client_credentials', - }; + Map requestBody = {'grant_type': 'client_credentials'}; - var response = await http.post(Uri.parse(apiUrl), - headers: { - 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'application/json', - }, - body: requestBody); + var response = await http.post( + Uri.parse(apiUrl), + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, + body: requestBody, + ); // Handle the response @@ -814,18 +943,32 @@ class GiftCardController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; String apiUrl = - orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -840,7 +983,11 @@ class GiftCardController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -854,7 +1001,9 @@ class GiftCardController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -871,12 +1020,13 @@ class GiftCardController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen( - initialURl: model.invoiceUrl ?? '', - transId: model.id ?? '', - apiKey: xenditModel.value.apiKey!.toString(), - ))! - .then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); placeOrder(); @@ -893,7 +1043,9 @@ class GiftCardController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -906,7 +1058,11 @@ class GiftCardController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/global_setting_controller.dart b/lib/controllers/global_setting_controller.dart index 1bcf70e..0eba1f1 100644 --- a/lib/controllers/global_setting_controller.dart +++ b/lib/controllers/global_setting_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/currency_model.dart'; import 'package:customer/models/user_model.dart'; import 'package:customer/utils/notification_service.dart'; import 'package:firebase_auth/firebase_auth.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/collection_name.dart'; import '../service/fire_store_utils.dart'; @@ -18,13 +18,27 @@ class GlobalSettingController extends GetxController { } Future getCurrentCurrency() async { - FireStoreUtils.fireStore.collection(CollectionName.currencies).where("isActive", isEqualTo: true).snapshots().listen((event) { - if (event.docs.isNotEmpty) { - Constant.currencyModel = CurrencyModel.fromJson(event.docs.first.data()); - } else { - Constant.currencyModel = CurrencyModel(id: "", code: "USD", decimal: 2, isactive: true, name: "US Dollar", symbol: "\$", symbolatright: false); - } - }); + FireStoreUtils.fireStore + .collection(CollectionName.currencies) + .where("isActive", isEqualTo: true) + .snapshots() + .listen((event) { + if (event.docs.isNotEmpty) { + Constant.currencyModel = CurrencyModel.fromJson( + event.docs.first.data(), + ); + } else { + Constant.currencyModel = CurrencyModel( + id: "", + code: "USD", + decimal: 2, + isactive: true, + name: "US Dollar", + symbol: "\$", + symbolatright: false, + ); + } + }); await FireStoreUtils.getSettings(); } @@ -35,7 +49,9 @@ class GlobalSettingController extends GetxController { String token = await NotificationService.getToken(); log(":::::::TOKEN:::::: $token"); if (FirebaseAuth.instance.currentUser != null) { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile( + FireStoreUtils.getCurrentUid(), + ).then((value) { if (value != null) { UserModel driverUserModel = value; driverUserModel.fcmToken = token; diff --git a/lib/controllers/history_gift_card_controller.dart b/lib/controllers/history_gift_card_controller.dart index 138b313..d11c857 100644 --- a/lib/controllers/history_gift_card_controller.dart +++ b/lib/controllers/history_gift_card_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/gift_cards_order_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:share_plus/share_plus.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class HistoryGiftCardController extends GetxController { RxList giftCardsOrderList = [].obs; @@ -25,13 +25,20 @@ class HistoryGiftCardController extends GetxController { void updateList(int index) { GiftCardsOrderModel giftCardsOrderModel = giftCardsOrderList[index]; - giftCardsOrderModel.isPasswordShow = giftCardsOrderModel.isPasswordShow == true ? false : true; + giftCardsOrderModel.isPasswordShow = + giftCardsOrderModel.isPasswordShow == true ? false : true; giftCardsOrderList.removeAt(index); giftCardsOrderList.insert(index, giftCardsOrderModel); } - Future share(String giftCode, String giftPin, String msg, String amount, Timestamp date) async { + Future share( + String giftCode, + String giftPin, + String msg, + String amount, + Timestamp date, + ) async { await Share.share( "${'Gift Code :'.tr()} $giftCode\n${'Gift Pin :'.tr()} $giftPin\n${'Price :'.tr()} ${Constant.amountShow(amount: amount)}\n${'Expire Date :'.tr()} ${date.toDate()}\n\n${'Message'.tr()} : $msg", ); diff --git a/lib/controllers/home_e_commerce_controller.dart b/lib/controllers/home_e_commerce_controller.dart index d92daa0..95adb18 100644 --- a/lib/controllers/home_e_commerce_controller.dart +++ b/lib/controllers/home_e_commerce_controller.dart @@ -8,8 +8,7 @@ import 'package:customer/models/vendor_model.dart'; import 'package:customer/service/cart_provider.dart'; import 'package:customer/service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../constant/constant.dart'; class HomeECommerceController extends GetxController { @@ -27,8 +26,10 @@ class HomeECommerceController extends GetxController { RxBool isListView = true.obs; RxBool isPopular = true.obs; - Rx pageController = PageController(viewportFraction: 0.877).obs; - Rx pageBottomController = PageController(viewportFraction: 0.877).obs; + Rx pageController = + PageController(viewportFraction: 0.877).obs; + Rx pageBottomController = + PageController(viewportFraction: 0.877).obs; RxInt currentPage = 0.obs; RxInt currentBottomPage = 0.obs; @@ -41,7 +42,8 @@ class HomeECommerceController extends GetxController { } RxList vendorCategoryModel = [].obs; - RxList categoryWiseProductList = [].obs; + RxList categoryWiseProductList = + [].obs; RxList allNearestRestaurant = [].obs; RxList newArrivalRestaurantList = [].obs; @@ -64,10 +66,22 @@ class HomeECommerceController extends GetxController { allNearestRestaurant.addAll(event); newArrivalRestaurantList.addAll(event); Constant.restaurantList = allNearestRestaurant; - List usedCategoryIds = allNearestRestaurant.expand((vendor) => vendor.categoryID ?? []).whereType().toSet().toList(); - vendorCategoryModel.value = vendorCategoryModel.where((category) => usedCategoryIds.contains(category.id)).toList(); + List usedCategoryIds = + allNearestRestaurant + .expand((vendor) => vendor.categoryID ?? []) + .whereType() + .toSet() + .toList(); + vendorCategoryModel.value = + vendorCategoryModel + .where((category) => usedCategoryIds.contains(category.id)) + .toList(); - newArrivalRestaurantList.sort((a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo((a.createdAt ?? Timestamp.now()).toDate())); + newArrivalRestaurantList.sort( + (a, b) => (b.createdAt ?? Timestamp.now()).toDate().compareTo( + (a.createdAt ?? Timestamp.now()).toDate(), + ), + ); if (Constant.isEnableAdsFeature == true) { await FireStoreUtils.getAllAdvertisement().then((value) { diff --git a/lib/controllers/home_parcel_controller.dart b/lib/controllers/home_parcel_controller.dart index aaccf75..f3e112f 100644 --- a/lib/controllers/home_parcel_controller.dart +++ b/lib/controllers/home_parcel_controller.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/banner_model.dart'; import '../models/parcel_category.dart'; import '../service/fire_store_utils.dart'; diff --git a/lib/controllers/live_tracking_controller.dart b/lib/controllers/live_tracking_controller.dart index dbc245c..9ec6f71 100644 --- a/lib/controllers/live_tracking_controller.dart +++ b/lib/controllers/live_tracking_controller.dart @@ -6,7 +6,7 @@ import 'package:customer/models/order_model.dart'; import 'package:customer/models/user_model.dart'; import 'package:customer/service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:latlong2/latlong.dart' as location; import 'package:flutter_map/flutter_map.dart' as flutterMap; @@ -59,37 +59,58 @@ class LiveTrackingController extends GetxController { orderModel.value = args['orderModel']; - orderSub = FireStoreUtils.fireStore.collection(CollectionName.vendorOrders).doc(orderModel.value.id).snapshots().listen((orderSnap) { - if (orderSnap.data() == null) return; - orderModel.value = OrderModel.fromJson(orderSnap.data()!); + orderSub = FireStoreUtils.fireStore + .collection(CollectionName.vendorOrders) + .doc(orderModel.value.id) + .snapshots() + .listen((orderSnap) { + if (orderSnap.data() == null) return; + orderModel.value = OrderModel.fromJson(orderSnap.data()!); - if (orderModel.value.driverID != null) { - driverSub?.cancel(); - driverSub = FireStoreUtils.fireStore.collection(CollectionName.users).doc(orderModel.value.driverID).snapshots().listen((driverSnap) async { - if (driverSnap.data() == null) return; - driverUserModel.value = UserModel.fromJson(driverSnap.data()!); - await updateLiveTracking(); + if (orderModel.value.driverID != null) { + driverSub?.cancel(); + driverSub = FireStoreUtils.fireStore + .collection(CollectionName.users) + .doc(orderModel.value.driverID) + .snapshots() + .listen((driverSnap) async { + if (driverSnap.data() == null) return; + driverUserModel.value = UserModel.fromJson( + driverSnap.data()!, + ); + await updateLiveTracking(); + }); + } + + if (orderModel.value.status == Constant.orderCompleted) { + Get.back(); + } }); - } - - if (orderModel.value.status == Constant.orderCompleted) { - Get.back(); - } - }); isLoading.value = false; } Future updateLiveTracking() async { - driverCurrent.value = location.LatLng(driverUserModel.value.location?.latitude ?? 0.0, driverUserModel.value.location?.longitude ?? 0.0); + driverCurrent.value = location.LatLng( + driverUserModel.value.location?.latitude ?? 0.0, + driverUserModel.value.location?.longitude ?? 0.0, + ); - source.value = location.LatLng(orderModel.value.vendor?.latitude ?? 0.0, orderModel.value.vendor?.longitude ?? 0.0); + source.value = location.LatLng( + orderModel.value.vendor?.latitude ?? 0.0, + orderModel.value.vendor?.longitude ?? 0.0, + ); - destination.value = location.LatLng(orderModel.value.address?.location?.latitude ?? 0.0, orderModel.value.address?.location?.longitude ?? 0.0); + destination.value = location.LatLng( + orderModel.value.address?.location?.latitude ?? 0.0, + orderModel.value.address?.location?.longitude ?? 0.0, + ); - if (orderModel.value.status == Constant.orderPlaced || orderModel.value.status == Constant.orderAccepted) { + if (orderModel.value.status == Constant.orderPlaced || + orderModel.value.status == Constant.orderAccepted) { await showDriverToRestaurantRoute(); - } else if (orderModel.value.status == Constant.orderShipped || orderModel.value.status == Constant.orderInTransit) { + } else if (orderModel.value.status == Constant.orderShipped || + orderModel.value.status == Constant.orderInTransit) { await showDriverToCustomerRoute(); } } @@ -136,7 +157,10 @@ class LiveTrackingController extends GetxController { routePoints.clear(); } - Future fetchRoute(location.LatLng source, location.LatLng destination) async { + Future fetchRoute( + location.LatLng source, + location.LatLng destination, + ) async { final url = Uri.parse( 'https://router.project-osrm.org/route/v1/driving/${source.longitude},${source.latitude};${destination.longitude},${destination.latitude}?overview=full&geometries=geojson', ); @@ -144,7 +168,12 @@ class LiveTrackingController extends GetxController { if (response.statusCode == 200) { final data = json.decode(response.body); final coords = data['routes'][0]['geometry']['coordinates']; - routePoints.value = coords.map((c) => location.LatLng(c[1].toDouble(), c[0].toDouble())).toList(); + routePoints.value = + coords + .map( + (c) => location.LatLng(c[1].toDouble(), c[0].toDouble()), + ) + .toList(); } } @@ -155,15 +184,34 @@ class LiveTrackingController extends GetxController { void addOsmMarkers({bool showPickup = false, bool showDrop = false}) { final List tempMarkers = [ // Driver Marker - flutterMap.Marker(point: driverCurrent.value, width: 40, height: 40, child: Image.asset('assets/images/food_delivery.png')), + flutterMap.Marker( + point: driverCurrent.value, + width: 40, + height: 40, + child: Image.asset('assets/images/food_delivery.png'), + ), ]; if (showPickup) { - tempMarkers.add(flutterMap.Marker(point: source.value, width: 40, height: 40, child: Image.asset('assets/images/pickup.png'))); + tempMarkers.add( + flutterMap.Marker( + point: source.value, + width: 40, + height: 40, + child: Image.asset('assets/images/pickup.png'), + ), + ); } if (showDrop) { - tempMarkers.add(flutterMap.Marker(point: destination.value, width: 40, height: 40, child: Image.asset('assets/images/dropoff.png'))); + tempMarkers.add( + flutterMap.Marker( + point: destination.value, + width: 40, + height: 40, + child: Image.asset('assets/images/dropoff.png'), + ), + ); } osmMarkers.value = tempMarkers; @@ -180,11 +228,16 @@ class LiveTrackingController extends GetxController { List polylineCoordinates = []; PolylineResult result = await polylinePoints.getRouteBetweenCoordinates( - request: PolylineRequest(origin: PointLatLng(sourceLatitude, sourceLongitude), destination: PointLatLng(destinationLatitude, destinationLongitude), mode: TravelMode.driving), + request: PolylineRequest( + origin: PointLatLng(sourceLatitude, sourceLongitude), + destination: PointLatLng(destinationLatitude, destinationLongitude), + mode: TravelMode.driving, + ), ); if (result.points.isNotEmpty) { - polylineCoordinates = result.points.map((e) => LatLng(e.latitude, e.longitude)).toList(); + polylineCoordinates = + result.points.map((e) => LatLng(e.latitude, e.longitude)).toList(); } addGoogleMarkers(showPickup: showPickup, showDrop: showDrop); @@ -205,9 +258,19 @@ class LiveTrackingController extends GetxController { ); } - if (showPickup && orderModel.value.vendor?.latitude != null && pickupIcon != null) { - addMarker(id: "Pickup", latitude: orderModel.value.vendor!.latitude ?? 0.0, longitude: orderModel.value.vendor!.longitude ?? 0.0, descriptor: pickupIcon!, rotation: 0.0); - } else if (showDrop && orderModel.value.address?.location?.latitude != null && dropoffIcon != null) { + if (showPickup && + orderModel.value.vendor?.latitude != null && + pickupIcon != null) { + addMarker( + id: "Pickup", + latitude: orderModel.value.vendor!.latitude ?? 0.0, + longitude: orderModel.value.vendor!.longitude ?? 0.0, + descriptor: pickupIcon!, + rotation: 0.0, + ); + } else if (showDrop && + orderModel.value.address?.location?.latitude != null && + dropoffIcon != null) { addMarker( id: "Drop", latitude: orderModel.value.address!.location!.latitude ?? 0.0, @@ -218,24 +281,50 @@ class LiveTrackingController extends GetxController { } } - void addMarker({required String id, required double latitude, required double longitude, required BitmapDescriptor descriptor, required double rotation}) { + void addMarker({ + required String id, + required double latitude, + required double longitude, + required BitmapDescriptor descriptor, + required double rotation, + }) { MarkerId markerId = MarkerId(id); - markers[markerId] = Marker(markerId: markerId, icon: descriptor, position: LatLng(latitude, longitude), rotation: rotation, anchor: const Offset(0.5, 0.5)); + markers[markerId] = Marker( + markerId: markerId, + icon: descriptor, + position: LatLng(latitude, longitude), + rotation: rotation, + anchor: const Offset(0.5, 0.5), + ); } Future addMarkerIcons() async { if (Constant.selectedMapType == 'osm') return; - pickupIcon = BitmapDescriptor.fromBytes(await Constant().getBytesFromAsset('assets/images/pickup.png', 100)); - dropoffIcon = BitmapDescriptor.fromBytes(await Constant().getBytesFromAsset('assets/images/dropoff.png', 100)); - driverIcon = BitmapDescriptor.fromBytes(await Constant().getBytesFromAsset('assets/images/food_delivery.png', 100)); + pickupIcon = BitmapDescriptor.fromBytes( + await Constant().getBytesFromAsset('assets/images/pickup.png', 100), + ); + dropoffIcon = BitmapDescriptor.fromBytes( + await Constant().getBytesFromAsset('assets/images/dropoff.png', 100), + ); + driverIcon = BitmapDescriptor.fromBytes( + await Constant().getBytesFromAsset( + 'assets/images/food_delivery.png', + 100, + ), + ); } Future _addPolyLine(List polylineCoordinates) async { if (polylineCoordinates.isEmpty) return; PolylineId id = const PolylineId("poly"); - Polyline polyline = Polyline(polylineId: id, color: Colors.blue, width: 5, points: polylineCoordinates); + Polyline polyline = Polyline( + polylineId: id, + color: Colors.blue, + width: 5, + points: polylineCoordinates, + ); polyLines[id] = polyline; await updateCameraBounds(polylineCoordinates); @@ -244,13 +333,26 @@ class LiveTrackingController extends GetxController { Future updateCameraBounds(List points) async { if (mapController == null || points.isEmpty) return; - double minLat = points.map((e) => e.latitude).reduce((a, b) => a < b ? a : b); - double maxLat = points.map((e) => e.latitude).reduce((a, b) => a > b ? a : b); - double minLng = points.map((e) => e.longitude).reduce((a, b) => a < b ? a : b); - double maxLng = points.map((e) => e.longitude).reduce((a, b) => a > b ? a : b); + double minLat = points + .map((e) => e.latitude) + .reduce((a, b) => a < b ? a : b); + double maxLat = points + .map((e) => e.latitude) + .reduce((a, b) => a > b ? a : b); + double minLng = points + .map((e) => e.longitude) + .reduce((a, b) => a < b ? a : b); + double maxLng = points + .map((e) => e.longitude) + .reduce((a, b) => a > b ? a : b); - LatLngBounds bounds = LatLngBounds(southwest: LatLng(minLat, minLng), northeast: LatLng(maxLat, maxLng)); + LatLngBounds bounds = LatLngBounds( + southwest: LatLng(minLat, minLng), + northeast: LatLng(maxLat, maxLng), + ); - await mapController!.animateCamera(CameraUpdate.newLatLngBounds(bounds, 80)); + await mapController!.animateCamera( + CameraUpdate.newLatLngBounds(bounds, 80), + ); } } diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index 132c7ad..3af30c4 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/screen_ui/location_enable_screens/location_permission_s import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_sign_in/google_sign_in.dart'; import 'package:sign_in_with_apple/sign_in_with_apple.dart'; import '../constant/constant.dart'; @@ -46,16 +46,22 @@ class LoginController extends GetxController { isLoading.value = true; ShowToastDialog.showLoader("Logging in...".tr()); - final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password); + final credential = await FirebaseAuth.instance.signInWithEmailAndPassword( + email: email, + password: password, + ); - final userModel = await FireStoreUtils.getUserProfile(credential.user!.uid); + final userModel = await FireStoreUtils.getUserProfile( + credential.user!.uid, + ); if (userModel != null && userModel.role == Constant.userRoleCustomer) { if (userModel.active == true) { userModel.fcmToken = await NotificationService.getToken(); await FireStoreUtils.updateUser(userModel); - if (userModel.shippingAddress != null && userModel.shippingAddress!.isNotEmpty) { + if (userModel.shippingAddress != null && + userModel.shippingAddress!.isNotEmpty) { final defaultAddress = userModel.shippingAddress!.firstWhere( (e) => e.isDefault == true, orElse: () => userModel.shippingAddress!.first, @@ -69,12 +75,16 @@ class LoginController extends GetxController { } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user is disabled. Please contact admin.".tr()); + ShowToastDialog.showToast( + "This user is disabled. Please contact admin.".tr(), + ); Get.offAll(() => const LoginScreen()); } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user does not exist in the customer app.".tr()); + ShowToastDialog.showToast( + "This user does not exist in the customer app.".tr(), + ); Get.offAll(() => const LoginScreen()); } } on FirebaseAuthException catch (e) { @@ -85,7 +95,9 @@ class LoginController extends GetxController { } else if (e.code == 'invalid-email') { ShowToastDialog.showToast("Invalid email.".tr()); } else { - ShowToastDialog.showToast(e.message?.tr() ?? "Login failed. Please try again.".tr()); + ShowToastDialog.showToast( + e.message?.tr() ?? "Login failed. Please try again.".tr(), + ); } } finally { isLoading.value = false; @@ -107,22 +119,32 @@ class LoginController extends GetxController { userModel.provider = 'google'; ShowToastDialog.closeLoader(); - Get.off(const SignUpScreen(), arguments: {"userModel": userModel, "type": "google"}); + Get.off( + const SignUpScreen(), + arguments: {"userModel": userModel, "type": "google"}, + ); } else { - await FireStoreUtils.userExistOrNot(value.user!.uid).then((userExit) async { + await FireStoreUtils.userExistOrNot(value.user!.uid).then(( + userExit, + ) async { ShowToastDialog.closeLoader(); if (userExit == true) { - UserModel? userModel = await FireStoreUtils.getUserProfile(value.user!.uid); - if (userModel != null && userModel.role == Constant.userRoleCustomer) { + UserModel? userModel = await FireStoreUtils.getUserProfile( + value.user!.uid, + ); + if (userModel != null && + userModel.role == Constant.userRoleCustomer) { if (userModel.active == true) { userModel.fcmToken = await NotificationService.getToken(); await FireStoreUtils.updateUser(userModel); - if (userModel.shippingAddress != null && userModel.shippingAddress!.isNotEmpty) { - final defaultAddress = userModel.shippingAddress!.firstWhere( - (e) => e.isDefault == true, - orElse: () => userModel.shippingAddress!.first, - ); + if (userModel.shippingAddress != null && + userModel.shippingAddress!.isNotEmpty) { + final defaultAddress = userModel.shippingAddress! + .firstWhere( + (e) => e.isDefault == true, + orElse: () => userModel.shippingAddress!.first, + ); Constant.selectedLocation = defaultAddress; @@ -132,12 +154,16 @@ class LoginController extends GetxController { } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user is disabled. Please contact admin.".tr()); + ShowToastDialog.showToast( + "This user is disabled. Please contact admin.".tr(), + ); Get.offAll(() => const LoginScreen()); } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user does not exist in the customer app.".tr()); + ShowToastDialog.showToast( + "This user does not exist in the customer app.".tr(), + ); Get.offAll(() => const LoginScreen()); } } else { @@ -148,7 +174,10 @@ class LoginController extends GetxController { userModel.lastName = value.user!.displayName?.split(' ').last; userModel.provider = 'google'; - Get.off(const SignUpScreen(), arguments: {"userModel": userModel, "type": "google"}); + Get.off( + const SignUpScreen(), + arguments: {"userModel": userModel, "type": "google"}, + ); } }); } @@ -174,22 +203,32 @@ class LoginController extends GetxController { userModel.lastName = appleCredential.familyName; userModel.provider = 'apple'; - Get.off(const SignUpScreen(), arguments: {"userModel": userModel, "type": "apple"}); + Get.off( + const SignUpScreen(), + arguments: {"userModel": userModel, "type": "apple"}, + ); } else { // Existing user - await FireStoreUtils.userExistOrNot(userCredential.user!.uid).then((userExit) async { + await FireStoreUtils.userExistOrNot(userCredential.user!.uid).then(( + userExit, + ) async { if (userExit == true) { - UserModel? userModel = await FireStoreUtils.getUserProfile(userCredential.user!.uid); - if (userModel != null && userModel.role == Constant.userRoleCustomer) { + UserModel? userModel = await FireStoreUtils.getUserProfile( + userCredential.user!.uid, + ); + if (userModel != null && + userModel.role == Constant.userRoleCustomer) { if (userModel.active == true) { userModel.fcmToken = await NotificationService.getToken(); await FireStoreUtils.updateUser(userModel); - if (userModel.shippingAddress != null && userModel.shippingAddress!.isNotEmpty) { - final defaultAddress = userModel.shippingAddress!.firstWhere( - (e) => e.isDefault == true, - orElse: () => userModel.shippingAddress!.first, - ); + if (userModel.shippingAddress != null && + userModel.shippingAddress!.isNotEmpty) { + final defaultAddress = userModel.shippingAddress! + .firstWhere( + (e) => e.isDefault == true, + orElse: () => userModel.shippingAddress!.first, + ); Constant.selectedLocation = defaultAddress; Get.offAll(() => const ServiceListScreen()); @@ -198,12 +237,16 @@ class LoginController extends GetxController { } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user is disabled. Please contact admin.".tr()); + ShowToastDialog.showToast( + "This user is disabled. Please contact admin.".tr(), + ); Get.offAll(() => const LoginScreen()); } } else { await FirebaseAuth.instance.signOut(); - ShowToastDialog.showToast("This user does not exist in the customer app.".tr()); + ShowToastDialog.showToast( + "This user does not exist in the customer app.".tr(), + ); Get.offAll(() => const LoginScreen()); } } else { @@ -215,7 +258,10 @@ class LoginController extends GetxController { userModel.lastName = appleCredential.familyName; userModel.provider = 'apple'; - Get.off(const SignUpScreen(), arguments: {"userModel": userModel, "type": "apple"}); + Get.off( + const SignUpScreen(), + arguments: {"userModel": userModel, "type": "apple"}, + ); } }); } @@ -234,8 +280,12 @@ class LoginController extends GetxController { final GoogleSignInAuthentication googleAuth = googleUser.authentication; - final credential = GoogleAuthProvider.credential(idToken: googleAuth.idToken); - final userCredential = await FirebaseAuth.instance.signInWithCredential(credential); + final credential = GoogleAuthProvider.credential( + idToken: googleAuth.idToken, + ); + final userCredential = await FirebaseAuth.instance.signInWithCredential( + credential, + ); return userCredential; } catch (e) { @@ -255,17 +305,27 @@ class LoginController extends GetxController { final rawNonce = generateNonce(); final nonce = sha256ofString(rawNonce); - AuthorizationCredentialAppleID appleCredential = await SignInWithApple.getAppleIDCredential( - scopes: [AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName], - nonce: nonce, + AuthorizationCredentialAppleID appleCredential = + await SignInWithApple.getAppleIDCredential( + scopes: [ + AppleIDAuthorizationScopes.email, + AppleIDAuthorizationScopes.fullName, + ], + nonce: nonce, + ); + + final oauthCredential = OAuthProvider("apple.com").credential( + idToken: appleCredential.identityToken, + rawNonce: rawNonce, + accessToken: appleCredential.authorizationCode, ); - final oauthCredential = OAuthProvider( - "apple.com", - ).credential(idToken: appleCredential.identityToken, rawNonce: rawNonce, accessToken: appleCredential.authorizationCode); - - UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential); - return {"appleCredential": appleCredential, "userCredential": userCredential}; + UserCredential userCredential = await FirebaseAuth.instance + .signInWithCredential(oauthCredential); + return { + "appleCredential": appleCredential, + "userCredential": userCredential, + }; } catch (e) { debugPrint(e.toString()); } diff --git a/lib/controllers/map_view_controller.dart b/lib/controllers/map_view_controller.dart index a7e148e..efa346f 100644 --- a/lib/controllers/map_view_controller.dart +++ b/lib/controllers/map_view_controller.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:customer/constant/constant.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart' as flutterMap; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:latlong2/latlong.dart' as location; import '../screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart'; diff --git a/lib/controllers/mobile_login_controller.dart b/lib/controllers/mobile_login_controller.dart index ddca48c..5717b2c 100644 --- a/lib/controllers/mobile_login_controller.dart +++ b/lib/controllers/mobile_login_controller.dart @@ -2,14 +2,15 @@ import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../constant/constant.dart'; import '../screen_ui/auth_screens/otp_verification_screen.dart'; class MobileLoginController extends GetxController { - final Rx mobileController = TextEditingController().obs; - final Rx countryCodeController = TextEditingController(text: Constant.defaultCountryCode).obs; + final Rx mobileController = + TextEditingController().obs; + final Rx countryCodeController = + TextEditingController(text: Constant.defaultCountryCode).obs; final FirebaseAuth _auth = FirebaseAuth.instance; @@ -19,7 +20,9 @@ class MobileLoginController extends GetxController { final countryCode = countryCodeController.value.text.trim(); if (mobile.isEmpty || mobile.length != 10) { - ShowToastDialog.showToast("Please enter a valid 10-digit mobile number".tr()); + ShowToastDialog.showToast( + "Please enter a valid 10-digit mobile number".tr(), + ); return; } @@ -36,12 +39,21 @@ class MobileLoginController extends GetxController { if (e.code == 'invalid-phone-number') { ShowToastDialog.showToast("Invalid phone number".tr()); } else { - ShowToastDialog.showToast(e.message ?? "OTP verification failed".tr()); + ShowToastDialog.showToast( + e.message ?? "OTP verification failed".tr(), + ); } }, codeSent: (String verificationId, int? resendToken) { ShowToastDialog.closeLoader(); - Get.to(() => const OtpVerificationScreen(), arguments: {'countryCode': countryCode, 'phoneNumber': mobile, 'verificationId': verificationId}); + Get.to( + () => const OtpVerificationScreen(), + arguments: { + 'countryCode': countryCode, + 'phoneNumber': mobile, + 'verificationId': verificationId, + }, + ); }, codeAutoRetrievalTimeout: (String verificationId) { ShowToastDialog.closeLoader(); diff --git a/lib/controllers/my_booking_on_demand_controller.dart b/lib/controllers/my_booking_on_demand_controller.dart index 150f4d5..6fc60e6 100644 --- a/lib/controllers/my_booking_on_demand_controller.dart +++ b/lib/controllers/my_booking_on_demand_controller.dart @@ -1,4 +1,4 @@ -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/onprovider_order_model.dart'; import '../models/worker_model.dart'; import '../service/fire_store_utils.dart'; @@ -18,7 +18,6 @@ class MyBookingOnDemandController extends GetxController { listenOrders(); // Listen for real-time updates } - void selectTab(String tab) { selectedTab.value = tab; } @@ -32,7 +31,9 @@ class MyBookingOnDemandController extends GetxController { // Fetch worker info if not already fetched for (var order in updatedOrders) { - if (order.workerId != null && order.workerId!.isNotEmpty && !workers.containsKey(order.workerId!)) { + if (order.workerId != null && + order.workerId!.isNotEmpty && + !workers.containsKey(order.workerId!)) { FireStoreUtils.getWorker(order.workerId!).then((worker) { if (worker != null) workers[order.workerId!] = worker; }); @@ -48,18 +49,39 @@ class MyBookingOnDemandController extends GetxController { ); } - List get filteredParcelOrders => getOrdersForTab(selectedTab.value); + List get filteredParcelOrders => + getOrdersForTab(selectedTab.value); List getOrdersForTab(String tab) { switch (tab) { case "Placed": - return orders.where((order) => ["Order Placed", "Order Accepted", "Order Assigned", "Order Ongoing", "In Transit"].contains(order.status)).toList(); + return orders + .where( + (order) => [ + "Order Placed", + "Order Accepted", + "Order Assigned", + "Order Ongoing", + "In Transit", + ].contains(order.status), + ) + .toList(); case "Completed": - return orders.where((order) => ["Order Completed"].contains(order.status)).toList(); + return orders + .where((order) => ["Order Completed"].contains(order.status)) + .toList(); case "Cancelled": - return orders.where((order) => ["Order Rejected", "Order Cancelled", "Driver Rejected"].contains(order.status)).toList(); + return orders + .where( + (order) => [ + "Order Rejected", + "Order Cancelled", + "Driver Rejected", + ].contains(order.status), + ) + .toList(); default: return []; diff --git a/lib/controllers/my_cab_booking_controller.dart b/lib/controllers/my_cab_booking_controller.dart index d563f7c..884a512 100644 --- a/lib/controllers/my_cab_booking_controller.dart +++ b/lib/controllers/my_cab_booking_controller.dart @@ -39,7 +39,7 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; @@ -72,7 +72,9 @@ class MyCabBookingController extends GetxController { isLoading.value = true; if (FirebaseAuth.instance.currentUser != null) { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((user) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + user, + ) { if (user != null) { userModel.value = user; } @@ -88,21 +90,45 @@ class MyCabBookingController extends GetxController { isLoading.value = false; } - List get filteredParcelOrders => getOrdersForTab(selectedTab.value); + List get filteredParcelOrders => + getOrdersForTab(selectedTab.value); List getOrdersForTab(String tab) { switch (tab) { case "New": - return cabOrder.where((order) => ["Order Placed", "Driver Pending"].contains(order.status)).toList(); + return cabOrder + .where( + (order) => + ["Order Placed", "Driver Pending"].contains(order.status), + ) + .toList(); case "On Going": - return cabOrder.where((order) => ["Driver Accepted", "Order Shipped", "In Transit"].contains(order.status)).toList(); + return cabOrder + .where( + (order) => [ + "Driver Accepted", + "Order Shipped", + "In Transit", + ].contains(order.status), + ) + .toList(); case "Completed": - return cabOrder.where((order) => ["Order Completed"].contains(order.status)).toList(); + return cabOrder + .where((order) => ["Order Completed"].contains(order.status)) + .toList(); case "Cancelled": - return cabOrder.where((order) => ["Order Rejected", "Order Cancelled", "Driver Rejected"].contains(order.status)).toList(); + return cabOrder + .where( + (order) => [ + "Order Rejected", + "Order Cancelled", + "Driver Rejected", + ].contains(order.status), + ) + .toList(); default: return []; @@ -164,15 +190,22 @@ class MyCabBookingController extends GetxController { selectedOrder.value = order; try { - subTotal.value = double.tryParse(selectedOrder.value.subTotal?.toString() ?? "0") ?? 0.0; - discount.value = double.tryParse(selectedOrder.value.discount?.toString() ?? "0") ?? 0.0; + subTotal.value = + double.tryParse(selectedOrder.value.subTotal?.toString() ?? "0") ?? + 0.0; + discount.value = + double.tryParse(selectedOrder.value.discount?.toString() ?? "0") ?? + 0.0; taxAmount.value = 0.0; subTotal.value = subTotal.value; if (selectedOrder.value.taxSetting != null) { for (var element in selectedOrder.value.taxSetting!) { - taxAmount.value += Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element); + taxAmount.value += Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + ); } } @@ -209,8 +242,13 @@ class MyCabBookingController extends GetxController { serviceType: Constant.parcelServiceType, ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ); }); } selectedOrder.value.paymentStatus = true; @@ -223,19 +261,45 @@ class MyCabBookingController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -277,20 +341,32 @@ class MyCabBookingController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -336,7 +412,10 @@ class MyCabBookingController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -346,8 +425,14 @@ class MyCabBookingController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -369,7 +454,11 @@ class MyCabBookingController extends GetxController { // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -452,15 +541,23 @@ class MyCabBookingController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -470,17 +567,23 @@ class MyCabBookingController extends GetxController { "payment_options": "ussd, card, barter, payattitude", "customer": { "email": Constant.userModel!.email.toString(), - "phonenumber": Constant.userModel!.phoneNumber, // Add a real phone number + "phonenumber": + Constant.userModel!.phoneNumber, // Add a real phone number "name": Constant.userModel!.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -509,10 +612,14 @@ class MyCabBookingController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: Constant.userModel!).then(( - String? value, - ) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: Constant.userModel!, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -594,7 +701,11 @@ class MyCabBookingController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), @@ -610,13 +721,18 @@ class MyCabBookingController extends GetxController { return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -634,9 +750,12 @@ class MyCabBookingController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -654,7 +773,10 @@ class MyCabBookingController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': Constant.userModel!.phoneNumber, 'email': Constant.userModel!.email}, + 'prefill': { + 'contact': Constant.userModel!.phoneNumber, + 'email': Constant.userModel!.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -689,7 +811,10 @@ class MyCabBookingController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -708,7 +833,9 @@ class MyCabBookingController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); final url = Uri.parse( - midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links', + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', ); final response = await http.post( @@ -716,12 +843,19 @@ class MyCabBookingController extends GetxController { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!), + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -729,7 +863,9 @@ class MyCabBookingController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -746,10 +882,18 @@ class MyCabBookingController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { Get.to( @@ -773,7 +917,12 @@ class MyCabBookingController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; @@ -794,9 +943,16 @@ class MyCabBookingController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -827,7 +983,11 @@ class MyCabBookingController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -841,7 +1001,9 @@ class MyCabBookingController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -859,7 +1021,11 @@ class MyCabBookingController extends GetxController { ShowToastDialog.closeLoader(); if (model.id != null) { Get.to( - () => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()), + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); @@ -877,7 +1043,9 @@ class MyCabBookingController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -890,7 +1058,11 @@ class MyCabBookingController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/my_profile_controller.dart b/lib/controllers/my_profile_controller.dart index 566b012..c6d7068 100644 --- a/lib/controllers/my_profile_controller.dart +++ b/lib/controllers/my_profile_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/controllers/theme_controller.dart'; import '../service/fire_store_utils.dart'; import 'package:customer/utils/preferences.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; class MyProfileController extends GetxController { @@ -41,7 +41,10 @@ class MyProfileController extends GetxController { Future deleteUserFromServer() async { var url = '${Constant.websiteUrl}/api/delete-user'; try { - var response = await http.post(Uri.parse(url), body: {'uuid': FireStoreUtils.getCurrentUid()}); + var response = await http.post( + Uri.parse(url), + body: {'uuid': FireStoreUtils.getCurrentUid()}, + ); log("deleteUserFromServer :: ${response.body}"); return response.statusCode == 200; } catch (e) { diff --git a/lib/controllers/my_rental_booking_controller.dart b/lib/controllers/my_rental_booking_controller.dart index 672ef22..3e595a7 100644 --- a/lib/controllers/my_rental_booking_controller.dart +++ b/lib/controllers/my_rental_booking_controller.dart @@ -5,7 +5,7 @@ import 'package:customer/models/wallet_transaction_model.dart'; import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/rental_order_model.dart'; import '../models/tax_model.dart'; import '../service/fire_store_utils.dart'; @@ -46,7 +46,6 @@ class MyRentalBookingController extends GetxController { ); } isLoading.value = false; - } Rx selectedOrder = RentalOrderModel().obs; @@ -67,38 +66,84 @@ class MyRentalBookingController extends GetxController { selectedOrder.value = order; try { - subTotal.value = double.tryParse(selectedOrder.value.subTotal?.toString() ?? "0") ?? 0.0; - discount.value = double.tryParse(selectedOrder.value.discount?.toString() ?? "0") ?? 0.0; + subTotal.value = + double.tryParse(selectedOrder.value.subTotal?.toString() ?? "0") ?? + 0.0; + discount.value = + double.tryParse(selectedOrder.value.discount?.toString() ?? "0") ?? + 0.0; taxAmount.value = 0.0; if (selectedOrder.value.endTime != null) { DateTime start = selectedOrder.value.startTime!.toDate(); DateTime end = selectedOrder.value.endTime!.toDate(); int hours = end.difference(start).inHours; - if (hours >= int.parse(selectedOrder.value.rentalPackageModel!.includedHours.toString())) { - hours = hours - int.parse(selectedOrder.value.rentalPackageModel!.includedHours.toString()); - double hourlyRate = double.tryParse(selectedOrder.value.rentalPackageModel?.extraMinuteFare?.toString() ?? "0") ?? 0.0; + if (hours >= + int.parse( + selectedOrder.value.rentalPackageModel!.includedHours.toString(), + )) { + hours = + hours - + int.parse( + selectedOrder.value.rentalPackageModel!.includedHours + .toString(), + ); + double hourlyRate = + double.tryParse( + selectedOrder.value.rentalPackageModel?.extraMinuteFare + ?.toString() ?? + "0", + ) ?? + 0.0; extraMinutesCharge.value = (hours * 60) * hourlyRate; } } - if (selectedOrder.value.startKitoMetersReading != null && selectedOrder.value.endKitoMetersReading != null) { - double startKm = double.tryParse(selectedOrder.value.startKitoMetersReading?.toString() ?? "0") ?? 0.0; - double endKm = double.tryParse(selectedOrder.value.endKitoMetersReading?.toString() ?? "0") ?? 0.0; + if (selectedOrder.value.startKitoMetersReading != null && + selectedOrder.value.endKitoMetersReading != null) { + double startKm = + double.tryParse( + selectedOrder.value.startKitoMetersReading?.toString() ?? "0", + ) ?? + 0.0; + double endKm = + double.tryParse( + selectedOrder.value.endKitoMetersReading?.toString() ?? "0", + ) ?? + 0.0; if (endKm > startKm) { double totalKm = endKm - startKm; - if (totalKm > double.parse(selectedOrder.value.rentalPackageModel!.includedDistance!)) { - totalKm = totalKm - double.parse(selectedOrder.value.rentalPackageModel!.includedDistance!); - double extraKmRate = double.tryParse(selectedOrder.value.rentalPackageModel?.extraKmFare?.toString() ?? "0") ?? 0.0; + if (totalKm > + double.parse( + selectedOrder.value.rentalPackageModel!.includedDistance!, + )) { + totalKm = + totalKm - + double.parse( + selectedOrder.value.rentalPackageModel!.includedDistance!, + ); + double extraKmRate = + double.tryParse( + selectedOrder.value.rentalPackageModel?.extraKmFare + ?.toString() ?? + "0", + ) ?? + 0.0; extraKilometerCharge.value = totalKm * extraKmRate; } } } - subTotal.value = subTotal.value + extraKilometerCharge.value + extraMinutesCharge.value; + subTotal.value = + subTotal.value + + extraKilometerCharge.value + + extraMinutesCharge.value; if (selectedOrder.value.taxSetting != null) { for (var element in selectedOrder.value.taxSetting!) { - taxAmount.value += Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element); + taxAmount.value += Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + ); } } @@ -134,9 +179,14 @@ class MyRentalBookingController extends GetxController { serviceType: Constant.parcelServiceType, ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.value.toString()}", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.value.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ); } }); } @@ -153,16 +203,42 @@ class MyRentalBookingController extends GetxController { List getOrdersForTab(String tab) { switch (tab) { case "New": - return rentalOrders.where((order) => ["Order Placed", "Order Accepted", "Driver Pending"].contains(order.status)).toList(); + return rentalOrders + .where( + (order) => [ + "Order Placed", + "Order Accepted", + "Driver Pending", + ].contains(order.status), + ) + .toList(); case "On Going": - return rentalOrders.where((order) => ["Driver Accepted", "Order Shipped", "In Transit"].contains(order.status)).toList(); + return rentalOrders + .where( + (order) => [ + "Driver Accepted", + "Order Shipped", + "In Transit", + ].contains(order.status), + ) + .toList(); case "Completed": - return rentalOrders.where((order) => ["Order Completed"].contains(order.status)).toList(); + return rentalOrders + .where((order) => ["Order Completed"].contains(order.status)) + .toList(); case "Cancelled": - return rentalOrders.where((order) => ["Order Rejected", "Order Cancelled", "Driver Rejected"].contains(order.status)).toList(); + return rentalOrders + .where( + (order) => [ + "Order Rejected", + "Order Cancelled", + "Driver Rejected", + ].contains(order.status), + ) + .toList(); default: return []; @@ -170,9 +246,13 @@ class MyRentalBookingController extends GetxController { } /// Old helper (optional) - List get filteredRentalOrders => getOrdersForTab(selectedTab.value); + List get filteredRentalOrders => + getOrdersForTab(selectedTab.value); - Future cancelRentalRequest(RentalOrderModel order, {List? taxList}) async { + Future cancelRentalRequest( + RentalOrderModel order, { + List? taxList, + }) async { try { isLoading.value = true; order.status = Constant.orderCancelled; @@ -186,13 +266,18 @@ class MyRentalBookingController extends GetxController { if (taxList != null) { for (var element in taxList) { totalTax += Constant.calculateTax( - amount: (double.parse(order.subTotal.toString()) - double.parse(order.discount.toString())).toString(), + amount: + (double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString())) + .toString(), taxModel: element, ); } } - double subTotal = double.parse(order.subTotal.toString()) - double.parse(order.discount.toString()); + double subTotal = + double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString()); double refundAmount = subTotal + totalTax; WalletTransactionModel walletTransaction = WalletTransactionModel( @@ -211,7 +296,10 @@ class MyRentalBookingController extends GetxController { ); await FireStoreUtils.setWalletTransaction(walletTransaction); - await FireStoreUtils.updateUserWallet(amount: refundAmount.toString(), userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: refundAmount.toString(), + userId: FireStoreUtils.getCurrentUid(), + ); } ShowToastDialog.showToast("Booking cancelled successfully".tr()); } catch (e) { diff --git a/lib/controllers/on_boarding_controller.dart b/lib/controllers/on_boarding_controller.dart index 178fbaf..eed931f 100644 --- a/lib/controllers/on_boarding_controller.dart +++ b/lib/controllers/on_boarding_controller.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/on_boarding_model.dart'; import '../service/fire_store_utils.dart'; diff --git a/lib/controllers/on_demand_booking_controller.dart b/lib/controllers/on_demand_booking_controller.dart index ebc84d3..dc73c5b 100644 --- a/lib/controllers/on_demand_booking_controller.dart +++ b/lib/controllers/on_demand_booking_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/models/user_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../models/onprovider_order_model.dart'; import '../models/provider_serivce_model.dart'; @@ -55,8 +55,12 @@ class OnDemandBookingController extends GetxController { void fetchCoupons() { if (provider.value?.author != null && provider.value!.author!.isNotEmpty) { - FireStoreUtils.getProviderCoupon(provider.value!.author!).then((activeCoupons) => couponList.assignAll(activeCoupons)); - FireStoreUtils.getProviderCouponAfterExpire(provider.value!.author!).then((expiredCoupons) => couponList.addAll(expiredCoupons)); + FireStoreUtils.getProviderCoupon( + provider.value!.author!, + ).then((activeCoupons) => couponList.assignAll(activeCoupons)); + FireStoreUtils.getProviderCouponAfterExpire( + provider.value!.author!, + ).then((expiredCoupons) => couponList.addAll(expiredCoupons)); } } @@ -80,8 +84,12 @@ class OnDemandBookingController extends GetxController { void applyCoupon(CouponModel coupon) { double discount = 0.0; - if (coupon.discountType == "Percentage" || coupon.discountType == "Percent") { - discount = price.value * (double.tryParse(coupon.discount.toString()) ?? 0) / 100; + if (coupon.discountType == "Percentage" || + coupon.discountType == "Percent") { + discount = + price.value * + (double.tryParse(coupon.discount.toString()) ?? 0) / + 100; } else { discount = double.tryParse(coupon.discount.toString()) ?? 0; } @@ -115,9 +123,14 @@ class OnDemandBookingController extends GetxController { // discount if (discountType.value == "Percentage" || discountType.value == "Percent") { - discountAmount.value = price.value * (double.tryParse(discountLabel.value) ?? 0) / 100; + discountAmount.value = + price.value * (double.tryParse(discountLabel.value) ?? 0) / 100; } else { - discountAmount.value = double.tryParse(discountLabel.value.isEmpty ? '0' : discountLabel.value) ?? 0; + discountAmount.value = + double.tryParse( + discountLabel.value.isEmpty ? '0' : discountLabel.value, + ) ?? + 0; } subTotal.value = price.value - discountAmount.value; @@ -125,7 +138,10 @@ class OnDemandBookingController extends GetxController { // tax calculation double total = subTotal.value; for (var element in Constant.taxList) { - total += Constant.getTaxValue(amount: subTotal.value.toString(), taxModel: element); + total += Constant.getTaxValue( + amount: subTotal.value.toString(), + taxModel: element, + ); } totalAmount.value = total; @@ -137,7 +153,9 @@ class OnDemandBookingController extends GetxController { } else if (dateTimeController.value.text.isEmpty) { ShowToastDialog.showToast("Please select time slot.".tr()); } else { - UserModel? providerUser = await FireStoreUtils.getUserProfile(provider.value!.author!); + UserModel? providerUser = await FireStoreUtils.getUserProfile( + provider.value!.author!, + ); if (provider.value?.priceUnit == "Fixed") { OnProviderOrderModel onDemandOrderModel = OnProviderOrderModel( @@ -161,14 +179,27 @@ class OnDemandBookingController extends GetxController { adminCommissionType: Constant.sectionConstantModel?.adminCommision?.isEnabled == false ? 'fixed' - : providerUser?.adminCommissionModel?.commissionType ?? Constant.sectionConstantModel?.adminCommision?.commissionType, + : providerUser?.adminCommissionModel?.commissionType ?? + Constant + .sectionConstantModel + ?.adminCommision + ?.commissionType, otp: Constant.getReferralCode(), couponCode: offerCode.toString(), ); - print('totalAmount ::::::: ${double.tryParse(Constant.amountShow(amount: totalAmount.value.toString())) ?? 0.0}'); + print( + 'totalAmount ::::::: ${double.tryParse(Constant.amountShow(amount: totalAmount.value.toString())) ?? 0.0}', + ); print('totalAmount value ::::::: ${totalAmount.value}'); - Get.to(() => OnDemandPaymentScreen(), arguments: {'onDemandOrderModel': Rxn(onDemandOrderModel), 'totalAmount': totalAmount.value, 'isExtra': false}); + Get.to( + () => OnDemandPaymentScreen(), + arguments: { + 'onDemandOrderModel': Rxn(onDemandOrderModel), + 'totalAmount': totalAmount.value, + 'isExtra': false, + }, + ); } else { ShowToastDialog.showLoader("Please wait...".tr()); OnProviderOrderModel onDemandOrder = OnProviderOrderModel( @@ -192,21 +223,36 @@ class OnDemandBookingController extends GetxController { adminCommissionType: Constant.sectionConstantModel?.adminCommision?.isEnabled == false ? 'fixed' - : providerUser?.adminCommissionModel?.commissionType ?? Constant.sectionConstantModel?.adminCommision?.commissionType, + : providerUser?.adminCommissionModel?.commissionType ?? + Constant + .sectionConstantModel + ?.adminCommision + ?.commissionType, paymentStatus: true, ); await FireStoreUtils.onDemandOrderPlace(onDemandOrder, 0.0); - await FireStoreUtils.sendOrderOnDemandServiceEmail(orderModel: onDemandOrder); + await FireStoreUtils.sendOrderOnDemandServiceEmail( + orderModel: onDemandOrder, + ); if (providerUser != null) { - Map payLoad = {"type": 'provider_order', "orderId": onDemandOrder.id}; - await SendNotification.sendFcmMessage(Constant.bookingPlaced, providerUser.fcmToken.toString(), payLoad); + Map payLoad = { + "type": 'provider_order', + "orderId": onDemandOrder.id, + }; + await SendNotification.sendFcmMessage( + Constant.bookingPlaced, + providerUser.fcmToken.toString(), + payLoad, + ); } ShowToastDialog.closeLoader(); Get.offAll(const OnDemandDashboardScreen()); - OnDemandDashboardController controller = Get.put(OnDemandDashboardController()); + OnDemandDashboardController controller = Get.put( + OnDemandDashboardController(), + ); controller.selectedIndex.value = 2; ShowToastDialog.showToast("OnDemand Service successfully booked".tr()); } diff --git a/lib/controllers/on_demand_category_controller.dart b/lib/controllers/on_demand_category_controller.dart index 31e6da0..1df529a 100644 --- a/lib/controllers/on_demand_category_controller.dart +++ b/lib/controllers/on_demand_category_controller.dart @@ -1,5 +1,4 @@ -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../models/category_model.dart'; import '../service/fire_store_utils.dart'; diff --git a/lib/controllers/on_demand_dashboard_controller.dart b/lib/controllers/on_demand_dashboard_controller.dart index 33b395c..a6f90f8 100644 --- a/lib/controllers/on_demand_dashboard_controller.dart +++ b/lib/controllers/on_demand_dashboard_controller.dart @@ -3,8 +3,7 @@ import 'package:customer/screen_ui/multi_vendor_service/profile_screen/profile_s import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/screen_ui/on_demand_service/favourite_ondemand_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../screen_ui/on_demand_service/my_booking_on_demand_screen.dart'; import '../screen_ui/on_demand_service/on_demand_home_screen.dart'; @@ -17,7 +16,12 @@ class OnDemandDashboardController extends GetxController { void onInit() { getTaxList(); if (Constant.walletSetting == false) { - pageList.value = [OnDemandHomeScreen(), FavouriteOndemandScreen(), const MyBookingOnDemandScreen(), const ProfileScreen()]; + pageList.value = [ + OnDemandHomeScreen(), + FavouriteOndemandScreen(), + const MyBookingOnDemandScreen(), + const ProfileScreen(), + ]; } else { pageList.value = [ OnDemandHomeScreen(), @@ -31,7 +35,9 @@ class OnDemandDashboardController extends GetxController { } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/on_demand_details_controller.dart b/lib/controllers/on_demand_details_controller.dart index 8f7ea01..a569994 100644 --- a/lib/controllers/on_demand_details_controller.dart +++ b/lib/controllers/on_demand_details_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/user_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../models/favorite_ondemand_service_model.dart'; import '../models/provider_serivce_model.dart'; @@ -14,7 +14,8 @@ class OnDemandDetailsController extends GetxController { final RxString subCategoryTitle = ''.obs; final RxString categoryTitle = ''.obs; final RxList ratingService = [].obs; - final RxList lstFav = [].obs; + final RxList lstFav = + [].obs; final RxBool isLoading = true.obs; final RxBool isOpen = false.obs; final RxString tabString = "About".obs; @@ -27,35 +28,44 @@ class OnDemandDetailsController extends GetxController { getData(); } - Future getData() async { await getReviewList(); await getAuthor(); //fetch and set provider author here if (Constant.userModel != null) { - lstFav.value = await FireStoreUtils.getFavouritesServiceList(FireStoreUtils.getCurrentUid()); + lstFav.value = await FireStoreUtils.getFavouritesServiceList( + FireStoreUtils.getCurrentUid(), + ); } isLoading.value = false; } Future getReviewList() async { - await FireStoreUtils.getCategoryById(provider.categoryId.toString()).then((value) { + await FireStoreUtils.getCategoryById(provider.categoryId.toString()).then(( + value, + ) { if (value != null) { categoryTitle.value = value.title.toString(); } }); - await FireStoreUtils.getSubCategoryById(provider.subCategoryId.toString()).then((value) { + await FireStoreUtils.getSubCategoryById( + provider.subCategoryId.toString(), + ).then((value) { if (value != null) { subCategoryTitle.value = value.title.toString(); } }); - await FireStoreUtils.getReviewByProviderServiceId(provider.id.toString()).then((value) { + await FireStoreUtils.getReviewByProviderServiceId( + provider.id.toString(), + ).then((value) { ratingService.value = value; }); if (Constant.userModel != null) { - await FireStoreUtils.getFavouritesServiceList(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getFavouritesServiceList( + FireStoreUtils.getCurrentUid(), + ).then((value) { lstFav.value = value; }); } @@ -78,8 +88,12 @@ class OnDemandDetailsController extends GetxController { for (var element in provider.days) { if (day == element.toString()) { - final start = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${provider.startTime}"); - final end = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${provider.endTime}"); + final start = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${provider.startTime}"); + final end = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${provider.endTime}"); if (isCurrentDateInRange(start, end)) { isOpen.value = true; } @@ -96,5 +110,3 @@ class OnDemandDetailsController extends GetxController { tabString.value = tab; } } - - diff --git a/lib/controllers/on_demand_home_controller.dart b/lib/controllers/on_demand_home_controller.dart index 16f4aac..2b609a8 100644 --- a/lib/controllers/on_demand_home_controller.dart +++ b/lib/controllers/on_demand_home_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/favorite_ondemand_service_model.dart'; import 'package:customer/models/provider_serivce_model.dart'; import 'package:customer/screen_ui/auth_screens/login_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../constant/constant.dart'; @@ -40,24 +40,31 @@ class OnDemandHomeController extends GetxController { // Fetch provider services FireStoreUtils.getProviderFuture() .then((providerServiceList) { - Set uniqueAuthorIds = providerServiceList.map((service) => service.author).toSet(); + Set uniqueAuthorIds = + providerServiceList.map((service) => service.author).toSet(); List listOfUniqueProviders = uniqueAuthorIds.toList(); List filteredProviders = []; for (var provider in listOfUniqueProviders) { - List filteredList = providerServiceList.where((service) => service.author == provider).toList(); + List filteredList = + providerServiceList + .where((service) => service.author == provider) + .toList(); filteredList.sort((a, b) => a.createdAt!.compareTo(b.createdAt!)); for (int index = 0; index < filteredList.length; index++) { final service = filteredList[index]; - if (Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel?.adminCommision?.isEnabled == true) { + if (Constant.isSubscriptionModelApplied == true || + Constant.sectionConstantModel?.adminCommision?.isEnabled == + true) { if (service.subscriptionPlan?.itemLimit == "-1") { filteredProviders.add(service); } else { - if (index < int.parse(service.subscriptionPlan?.itemLimit ?? '0')) { + if (index < + int.parse(service.subscriptionPlan?.itemLimit ?? '0')) { filteredProviders.add(service); } } @@ -75,7 +82,9 @@ class OnDemandHomeController extends GetxController { isLoading.value = false; }); - FireStoreUtils.getFavouritesServiceList(FireStoreUtils.getCurrentUid()).then((favList) { + FireStoreUtils.getFavouritesServiceList( + FireStoreUtils.getCurrentUid(), + ).then((favList) { lstFav.value = favList; }); } @@ -85,7 +94,9 @@ class OnDemandHomeController extends GetxController { if (categoryId == null || categoryId.isEmpty) return null; // Try to find category from cached list - CategoryModel? cat = categories.firstWhereOrNull((element) => element.id == categoryId); + CategoryModel? cat = categories.firstWhereOrNull( + (element) => element.id == categoryId, + ); // If not found, fetch from Firestore cat ??= await FireStoreUtils.getCategoryById(categoryId); @@ -94,29 +105,34 @@ class OnDemandHomeController extends GetxController { return cat; } - RxList lstFav = [].obs; + RxList lstFav = + [].obs; void toggleFavourite(ProviderServiceModel provider) { if (Constant.userModel == null) { Get.to(LoginScreen()); } else { - var contain = lstFav.where((element) => element.service_id == provider.id); + var contain = lstFav.where( + (element) => element.service_id == provider.id, + ); if (contain.isNotEmpty) { - FavouriteOndemandServiceModel favouriteModel = FavouriteOndemandServiceModel( - section_id: provider.sectionId, - service_id: provider.id, - user_id: FireStoreUtils.getCurrentUid(), - serviceAuthorId: provider.author, - ); + FavouriteOndemandServiceModel favouriteModel = + FavouriteOndemandServiceModel( + section_id: provider.sectionId, + service_id: provider.id, + user_id: FireStoreUtils.getCurrentUid(), + serviceAuthorId: provider.author, + ); FireStoreUtils.removeFavouriteOndemandService(favouriteModel); lstFav.removeWhere((item) => item.service_id == provider.id); } else { - FavouriteOndemandServiceModel favouriteModel = FavouriteOndemandServiceModel( - section_id: provider.sectionId, - service_id: provider.id, - user_id: FireStoreUtils.getCurrentUid(), - serviceAuthorId: provider.author, - ); + FavouriteOndemandServiceModel favouriteModel = + FavouriteOndemandServiceModel( + section_id: provider.sectionId, + service_id: provider.id, + user_id: FireStoreUtils.getCurrentUid(), + serviceAuthorId: provider.author, + ); FireStoreUtils.setFavouriteOndemandSection(favouriteModel); lstFav.add(favouriteModel); } @@ -127,7 +143,13 @@ class OnDemandHomeController extends GetxController { await FireStoreUtils.getZone().then((value) { if (value != null) { for (int i = 0; i < value.length; i++) { - if (Constant.isPointInPolygon(LatLng(Constant.selectedLocation.location?.latitude ?? 0.0, Constant.selectedLocation.location?.longitude ?? 0.0), value[i].area!)) { + if (Constant.isPointInPolygon( + LatLng( + Constant.selectedLocation.location?.latitude ?? 0.0, + Constant.selectedLocation.location?.longitude ?? 0.0, + ), + value[i].area!, + )) { Constant.selectedZone = value[i]; Constant.isZoneAvailable = true; break; diff --git a/lib/controllers/on_demand_order_details_controller.dart b/lib/controllers/on_demand_order_details_controller.dart index 3860ac7..afab172 100644 --- a/lib/controllers/on_demand_order_details_controller.dart +++ b/lib/controllers/on_demand_order_details_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/models/user_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/constant.dart'; import '../models/onprovider_order_model.dart'; import '../models/wallet_transaction_model.dart'; @@ -19,7 +19,8 @@ class OnDemandOrderDetailsController extends GetxController { Rxn worker = Rxn(); Rx couponTextController = TextEditingController().obs; - Rx cancelBookingController = TextEditingController().obs; + Rx cancelBookingController = + TextEditingController().obs; RxDouble subTotal = 0.0.obs; RxDouble price = 0.0.obs; @@ -48,17 +49,22 @@ class OnDemandOrderDetailsController extends GetxController { Future getData() async { try { - final order = await FireStoreUtils.getProviderOrderById(onProviderOrder.value!.id); + final order = await FireStoreUtils.getProviderOrderById( + onProviderOrder.value!.id, + ); if (order != null) { onProviderOrder.value = order; discountType.value = order.discountType ?? ""; discountLabel.value = order.discountLabel ?? ""; - discountAmount.value = double.tryParse(order.discount.toString()) ?? 0.0; + discountAmount.value = + double.tryParse(order.discount.toString()) ?? 0.0; offerCode.value = order.couponCode ?? ""; // Fetch provider - providerUser.value = await FireStoreUtils.getUserProfile(order.provider.author.toString()); + providerUser.value = await FireStoreUtils.getUserProfile( + order.provider.author.toString(), + ); // Fetch worker (if exists) if (order.workerId != null && order.workerId!.isNotEmpty) { @@ -70,7 +76,9 @@ class OnDemandOrderDetailsController extends GetxController { calculatePrice(); // Load available coupons - FireStoreUtils.getProviderCouponAfterExpire(order.provider.author.toString()).then((expiredCoupons) { + FireStoreUtils.getProviderCouponAfterExpire( + order.provider.author.toString(), + ).then((expiredCoupons) { couponList.assignAll(expiredCoupons); }); } else { @@ -90,8 +98,12 @@ class OnDemandOrderDetailsController extends GetxController { void applyCoupon(CouponModel coupon) { double discount = 0.0; - if (coupon.discountType == "Percentage" || coupon.discountType == "Percent") { - discount = price.value * (double.tryParse(coupon.discount.toString()) ?? 0) / 100; + if (coupon.discountType == "Percentage" || + coupon.discountType == "Percent") { + discount = + price.value * + (double.tryParse(coupon.discount.toString()) ?? 0) / + 100; } else { discount = double.tryParse(coupon.discount.toString()) ?? 0; } @@ -108,17 +120,29 @@ class OnDemandOrderDetailsController extends GetxController { void calculatePrice() { double basePrice = - (onProviderOrder.value?.provider.disPrice == "" || onProviderOrder.value?.provider.disPrice == "0") - ? double.tryParse(onProviderOrder.value?.provider.price.toString() ?? "0") ?? 0 - : double.tryParse(onProviderOrder.value?.provider.disPrice.toString() ?? "0") ?? 0; + (onProviderOrder.value?.provider.disPrice == "" || + onProviderOrder.value?.provider.disPrice == "0") + ? double.tryParse( + onProviderOrder.value?.provider.price.toString() ?? "0", + ) ?? + 0 + : double.tryParse( + onProviderOrder.value?.provider.disPrice.toString() ?? "0", + ) ?? + 0; price.value = basePrice * (onProviderOrder.value?.quantity ?? 0.0); // discount if (discountType.value == "Percentage" || discountType.value == "Percent") { - discountAmount.value = price.value * (double.tryParse(discountLabel.value) ?? 0) / 100; + discountAmount.value = + price.value * (double.tryParse(discountLabel.value) ?? 0) / 100; } else { - discountAmount.value = double.tryParse(discountLabel.value.isEmpty ? '0' : discountLabel.value) ?? 0; + discountAmount.value = + double.tryParse( + discountLabel.value.isEmpty ? '0' : discountLabel.value, + ) ?? + 0; } subTotal.value = price.value - discountAmount.value; @@ -126,7 +150,10 @@ class OnDemandOrderDetailsController extends GetxController { // tax calculation double total = subTotal.value; for (var element in Constant.taxList) { - total += Constant.getTaxValue(amount: subTotal.value.toString(), taxModel: element); + total += Constant.getTaxValue( + amount: subTotal.value.toString(), + taxModel: element, + ); } totalAmount.value = total; @@ -152,22 +179,30 @@ class OnDemandOrderDetailsController extends GetxController { // Calculate total final pricePerUnit = - (order.provider.disPrice == "" || order.provider.disPrice == "0") ? double.tryParse(order.provider.price.toString()) ?? 0 : double.tryParse(order.provider.disPrice.toString()) ?? 0; + (order.provider.disPrice == "" || order.provider.disPrice == "0") + ? double.tryParse(order.provider.price.toString()) ?? 0 + : double.tryParse(order.provider.disPrice.toString()) ?? 0; total = pricePerUnit * (order.quantity); // Add tax if (Constant.taxList.isNotEmpty) { for (var tax in Constant.taxList) { - total += Constant.getTaxValue(amount: total.toString(), taxModel: tax); + total += Constant.getTaxValue( + amount: total.toString(), + taxModel: tax, + ); } } // Admin commission double adminComm = 0.0; - if ((order.adminCommission ?? '0') != '0' && (order.adminCommissionType ?? '').isNotEmpty) { - if (order.adminCommissionType!.toLowerCase() == 'percentage' || order.adminCommissionType!.toLowerCase() == 'percent') { - adminComm = (total * (double.tryParse(order.adminCommission!) ?? 0)) / 100; + if ((order.adminCommission ?? '0') != '0' && + (order.adminCommissionType ?? '').isNotEmpty) { + if (order.adminCommissionType!.toLowerCase() == 'percentage' || + order.adminCommissionType!.toLowerCase() == 'percent') { + adminComm = + (total * (double.tryParse(order.adminCommission!) ?? 0)) / 100; } else { adminComm = double.tryParse(order.adminCommission!) ?? 0; } @@ -237,10 +272,19 @@ class OnDemandOrderDetailsController extends GetxController { await FireStoreUtils.updateOnDemandOrder(order); // Ensure this completes // Notify provider - final provider = await FireStoreUtils.getUserProfile(order.provider.author ?? ''); + final provider = await FireStoreUtils.getUserProfile( + order.provider.author ?? '', + ); if (provider != null) { - Map payload = {"type": 'provider_order', "orderId": order.id}; - await SendNotification.sendFcmMessage(Constant.bookingPlaced, provider.fcmToken ?? '', payload); + Map payload = { + "type": 'provider_order', + "orderId": order.id, + }; + await SendNotification.sendFcmMessage( + Constant.bookingPlaced, + provider.fcmToken ?? '', + payload, + ); } ShowToastDialog.closeLoader(); diff --git a/lib/controllers/on_demand_review_controller.dart b/lib/controllers/on_demand_review_controller.dart index 4d82f52..a5ea0a0 100644 --- a/lib/controllers/on_demand_review_controller.dart +++ b/lib/controllers/on_demand_review_controller.dart @@ -1,7 +1,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/collection_name.dart'; import '../models/onprovider_order_model.dart'; import '../models/provider_serivce_model.dart'; @@ -20,7 +20,8 @@ class OnDemandReviewController extends GetxController { final TextEditingController comment = TextEditingController(); final Rxn provider = Rxn(); - final Rxn providerServiceModel = Rxn(); + final Rxn providerServiceModel = + Rxn(); final Rxn workerModel = Rxn(); final RxInt providerReviewCount = 0.obs; @@ -46,14 +47,20 @@ class OnDemandReviewController extends GetxController { void getReview() async { // Get existing rating if (reviewFor.value == "Provider") { - RatingModel? value = await FireStoreUtils.getReviewsByProviderID(order.value!.id, order.value!.provider.author.toString()); + RatingModel? value = await FireStoreUtils.getReviewsByProviderID( + order.value!.id, + order.value!.provider.author.toString(), + ); if (value != null) { ratingModel.value = value; ratings.value = value.rating ?? 0.0; comment.text = value.comment ?? ''; } } else { - RatingModel? value = await FireStoreUtils.getReviewsByWorkerID(order.value!.id, order.value!.workerId.toString()); + RatingModel? value = await FireStoreUtils.getReviewsByWorkerID( + order.value!.id, + order.value!.workerId.toString(), + ); if (value != null) { ratingModel.value = value; ratings.value = value.rating ?? 0.0; @@ -63,7 +70,9 @@ class OnDemandReviewController extends GetxController { // Worker review logic if (reviewFor.value == "Worker") { - WorkerModel? value = await FireStoreUtils.getWorker(order.value!.workerId.toString()); + WorkerModel? value = await FireStoreUtils.getWorker( + order.value!.workerId.toString(), + ); if (value != null) { workerModel.value = value; @@ -71,25 +80,35 @@ class OnDemandReviewController extends GetxController { final double existingSum = (value.reviewsSum ?? 0.0).toDouble(); final double oldRating = ratingModel.value?.rating ?? 0.0; - workerReviewCount.value = ratingModel.value != null ? (existingCount - 1) : existingCount; - workerReviewSum.value = ratingModel.value != null ? (existingSum - oldRating) : existingSum; + workerReviewCount.value = + ratingModel.value != null ? (existingCount - 1) : existingCount; + workerReviewSum.value = + ratingModel.value != null ? (existingSum - oldRating) : existingSum; } } // Provider & service review logic else { - UserModel? user = await FireStoreUtils.getUserProfile(order.value!.provider.author.toString()); + UserModel? user = await FireStoreUtils.getUserProfile( + order.value!.provider.author.toString(), + ); if (user != null) { provider.value = user; - final int existingCount = int.tryParse(user.reviewsCount?.toString() ?? '0') ?? 0; - final double existingSum = double.tryParse(user.reviewsSum?.toString() ?? '0.0') ?? 0.0; + final int existingCount = + int.tryParse(user.reviewsCount?.toString() ?? '0') ?? 0; + final double existingSum = + double.tryParse(user.reviewsSum?.toString() ?? '0.0') ?? 0.0; final double oldRating = ratingModel.value?.rating ?? 0.0; - providerReviewCount.value = ratingModel.value != null ? (existingCount - 1) : existingCount; - providerReviewSum.value = ratingModel.value != null ? (existingSum - oldRating) : existingSum; + providerReviewCount.value = + ratingModel.value != null ? (existingCount - 1) : existingCount; + providerReviewSum.value = + ratingModel.value != null ? (existingSum - oldRating) : existingSum; } - ProviderServiceModel? service = await FireStoreUtils.getCurrentProvider(order.value!.provider.id.toString()); + ProviderServiceModel? service = await FireStoreUtils.getCurrentProvider( + order.value!.provider.id.toString(), + ); if (service != null) { providerServiceModel.value = service; @@ -97,8 +116,10 @@ class OnDemandReviewController extends GetxController { final double existingSum = (service.reviewsSum ?? 0.0).toDouble(); final double oldRating = ratingModel.value?.rating ?? 0.0; - serviceReviewCount.value = ratingModel.value != null ? (existingCount - 1) : existingCount; - serviceReviewSum.value = ratingModel.value != null ? (existingSum - oldRating) : existingSum; + serviceReviewCount.value = + ratingModel.value != null ? (existingCount - 1) : existingCount; + serviceReviewSum.value = + ratingModel.value != null ? (existingSum - oldRating) : existingSum; } } } @@ -114,22 +135,29 @@ class OnDemandReviewController extends GetxController { Future _providerReviewSubmit() async { ShowToastDialog.showLoader("Submit in...".tr()); providerServiceModel.value!.reviewsCount = serviceReviewCount.value + 1; - providerServiceModel.value!.reviewsSum = serviceReviewSum.value + ratings.value; + providerServiceModel.value!.reviewsSum = + serviceReviewSum.value + ratings.value; // Convert to string only if your model field is String provider.value!.reviewsCount = (providerReviewCount.value + 1).toString(); - provider.value!.reviewsSum = (providerReviewSum.value + ratings.value).toString(); + provider.value!.reviewsSum = + (providerReviewSum.value + ratings.value).toString(); RatingModel rate = RatingModel( - id: ratingModel.value?.id ?? firestore.collection(CollectionName.itemsReview).doc().id, + id: + ratingModel.value?.id ?? + firestore.collection(CollectionName.itemsReview).doc().id, productId: ratingModel.value?.productId ?? order.value!.provider.id, comment: comment.text, photos: ratingModel.value?.photos ?? [], rating: ratings.value, orderId: ratingModel.value?.orderId ?? order.value!.id, - vendorId: ratingModel.value?.vendorId ?? order.value!.provider.author.toString(), + vendorId: + ratingModel.value?.vendorId ?? + order.value!.provider.author.toString(), customerId: Constant.userModel?.id, - uname: '${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}', + uname: + '${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}', profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); @@ -148,7 +176,9 @@ class OnDemandReviewController extends GetxController { workerModel.value!.reviewsSum = workerReviewSum.value + ratings.value; RatingModel rate = RatingModel( - id: ratingModel.value?.id ?? firestore.collection(CollectionName.itemsReview).doc().id, + id: + ratingModel.value?.id ?? + firestore.collection(CollectionName.itemsReview).doc().id, productId: ratingModel.value?.productId ?? order.value!.provider.id, comment: comment.text, photos: ratingModel.value?.photos ?? [], @@ -156,7 +186,8 @@ class OnDemandReviewController extends GetxController { orderId: ratingModel.value?.orderId ?? order.value!.id, driverId: ratingModel.value?.driverId ?? order.value!.workerId.toString(), customerId: Constant.userModel?.id, - uname: '${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}', + uname: + '${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}', profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); diff --git a/lib/controllers/order_controller.dart b/lib/controllers/order_controller.dart index c6b606b..7c39996 100644 --- a/lib/controllers/order_controller.dart +++ b/lib/controllers/order_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/models/cart_product_model.dart'; import 'package:customer/models/order_model.dart'; import '../service/cart_provider.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class OrderController extends GetxController { RxList allList = [].obs; @@ -26,16 +26,27 @@ class OrderController extends GetxController { await FireStoreUtils.getAllOrder().then((value) { allList.value = value; - rejectedList.value = allList.where((p0) => p0.status == Constant.orderRejected).toList(); + rejectedList.value = + allList.where((p0) => p0.status == Constant.orderRejected).toList(); inProgressList.value = allList .where( - (p0) => p0.status == Constant.orderAccepted || p0.status == Constant.driverPending || p0.status == Constant.orderShipped || p0.status == Constant.orderInTransit, + (p0) => + p0.status == Constant.orderAccepted || + p0.status == Constant.driverPending || + p0.status == Constant.orderShipped || + p0.status == Constant.orderInTransit, ) .toList(); - deliveredList.value = allList.where((p0) => p0.status == Constant.orderCompleted).toList(); - cancelledList.value = allList.where((p0) => p0.status == Constant.orderCancelled).toList(); + deliveredList.value = + allList + .where((p0) => p0.status == Constant.orderCompleted) + .toList(); + cancelledList.value = + allList + .where((p0) => p0.status == Constant.orderCancelled) + .toList(); }); } @@ -45,7 +56,11 @@ class OrderController extends GetxController { final CartProvider cartProvider = CartProvider(); void addToCart({required CartProductModel cartProductModel}) { - cartProvider.addToCart(Get.context!, cartProductModel, cartProductModel.quantity!); + cartProvider.addToCart( + Get.context!, + cartProductModel, + cartProductModel.quantity!, + ); update(); } } diff --git a/lib/controllers/order_details_controller.dart b/lib/controllers/order_details_controller.dart index 44c2898..e1a51fa 100644 --- a/lib/controllers/order_details_controller.dart +++ b/lib/controllers/order_details_controller.dart @@ -1,8 +1,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/cart_product_model.dart'; import 'package:customer/models/order_model.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../service/cart_provider.dart'; class OrderDetailsController extends GetxController { @@ -39,28 +38,48 @@ class OrderDetailsController extends GetxController { for (var element in orderModel.value.products!) { if (double.parse(element.discountPrice.toString()) <= 0) { - subTotal.value = subTotal.value + - double.parse(element.price.toString()) * double.parse(element.quantity.toString()) + - (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); + subTotal.value = + subTotal.value + + double.parse(element.price.toString()) * + double.parse(element.quantity.toString()) + + (double.parse(element.extrasPrice.toString()) * + double.parse(element.quantity.toString())); } else { - subTotal.value = subTotal.value + - double.parse(element.discountPrice.toString()) * double.parse(element.quantity.toString()) + - (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); + subTotal.value = + subTotal.value + + double.parse(element.discountPrice.toString()) * + double.parse(element.quantity.toString()) + + (double.parse(element.extrasPrice.toString()) * + double.parse(element.quantity.toString())); } } - if (orderModel.value.specialDiscount != null && orderModel.value.specialDiscount!['special_discount'] != null) { - specialDiscountAmount.value = double.parse(orderModel.value.specialDiscount!['special_discount'].toString()); + if (orderModel.value.specialDiscount != null && + orderModel.value.specialDiscount!['special_discount'] != null) { + specialDiscountAmount.value = double.parse( + orderModel.value.specialDiscount!['special_discount'].toString(), + ); } if (orderModel.value.taxSetting != null) { for (var element in orderModel.value.taxSetting!) { - taxAmount.value = taxAmount.value + - Constant.calculateTax(amount: (subTotal.value - double.parse(orderModel.value.discount.toString()) - specialDiscountAmount.value).toString(), taxModel: element); + taxAmount.value = + taxAmount.value + + Constant.calculateTax( + amount: + (subTotal.value - + double.parse(orderModel.value.discount.toString()) - + specialDiscountAmount.value) + .toString(), + taxModel: element, + ); } } - totalAmount.value = (subTotal.value - double.parse(orderModel.value.discount.toString()) - specialDiscountAmount.value) + + totalAmount.value = + (subTotal.value - + double.parse(orderModel.value.discount.toString()) - + specialDiscountAmount.value) + taxAmount.value + double.parse(orderModel.value.deliveryCharge.toString()) + double.parse(orderModel.value.tipAmount.toString()); @@ -71,7 +90,11 @@ class OrderDetailsController extends GetxController { final CartProvider cartProvider = CartProvider(); void addToCart({required CartProductModel cartProductModel}) { - cartProvider.addToCart(Get.context!, cartProductModel, cartProductModel.quantity!); + cartProvider.addToCart( + Get.context!, + cartProductModel, + cartProductModel.quantity!, + ); update(); } } diff --git a/lib/controllers/order_placing_controller.dart b/lib/controllers/order_placing_controller.dart index fa489d6..5fa8060 100644 --- a/lib/controllers/order_placing_controller.dart +++ b/lib/controllers/order_placing_controller.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'package:customer/models/order_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../service/database_helper.dart'; class OrderPlacingController extends GetxController { diff --git a/lib/controllers/osm_search_place_controller.dart b/lib/controllers/osm_search_place_controller.dart index 7cdf1e2..be7afab 100644 --- a/lib/controllers/osm_search_place_controller.dart +++ b/lib/controllers/osm_search_place_controller.dart @@ -1,7 +1,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_osm_plugin/flutter_osm_plugin.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:shared_preferences/shared_preferences.dart'; class OsmSearchPlaceController extends GetxController { @@ -25,7 +25,8 @@ class OsmSearchPlaceController extends GetxController { try { String locale = 'en'; SharedPreferences sp = await SharedPreferences.getInstance(); - if (sp.getString("languageCode") != null || sp.getString("languageCode")?.isNotEmpty == true) { + if (sp.getString("languageCode") != null || + sp.getString("languageCode")?.isNotEmpty == true) { locale = sp.getString("languageCode") ?? "en"; } suggestionsList.value = await addressSuggestion(text, locale: locale); diff --git a/lib/controllers/otp_verification_controller.dart b/lib/controllers/otp_verification_controller.dart index f33f250..745082a 100644 --- a/lib/controllers/otp_verification_controller.dart +++ b/lib/controllers/otp_verification_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/constant.dart'; import '../models/user_model.dart'; import '../screen_ui/auth_screens/login_screen.dart'; @@ -63,15 +63,27 @@ class OtpVerifyController extends GetxController { try { ShowToastDialog.showLoader("Verifying OTP...".tr()); - final credential = PhoneAuthProvider.credential(verificationId: verificationId.value, smsCode: otpController.value.text.trim()); + final credential = PhoneAuthProvider.credential( + verificationId: verificationId.value, + smsCode: otpController.value.text.trim(), + ); final fcmToken = await NotificationService.getToken(); final result = await _auth.signInWithCredential(credential); if (result.additionalUserInfo?.isNewUser == true) { - final userModel = UserModel(id: result.user!.uid, countryCode: countryCode.value, phoneNumber: phoneNumber.value, fcmToken: fcmToken, active: true); + final userModel = UserModel( + id: result.user!.uid, + countryCode: countryCode.value, + phoneNumber: phoneNumber.value, + fcmToken: fcmToken, + active: true, + ); ShowToastDialog.closeLoader(); - Get.to(() => const SignUpScreen(), arguments: {'type': 'mobileNumber', 'userModel': userModel}); + Get.to( + () => const SignUpScreen(), + arguments: {'type': 'mobileNumber', 'userModel': userModel}, + ); return; } @@ -79,8 +91,16 @@ class OtpVerifyController extends GetxController { ShowToastDialog.closeLoader(); if (!exists) { - final userModel = UserModel(id: result.user!.uid, countryCode: countryCode.value, phoneNumber: phoneNumber.value, fcmToken: fcmToken); - Get.off(() => const SignUpScreen(), arguments: {'type': 'mobileNumber', 'userModel': userModel}); + final userModel = UserModel( + id: result.user!.uid, + countryCode: countryCode.value, + phoneNumber: phoneNumber.value, + fcmToken: fcmToken, + ); + Get.off( + () => const SignUpScreen(), + arguments: {'type': 'mobileNumber', 'userModel': userModel}, + ); return; } @@ -102,7 +122,10 @@ class OtpVerifyController extends GetxController { await FireStoreUtils.updateUser(userModel); if (userModel.shippingAddress?.isNotEmpty ?? false) { - final defaultAddress = userModel.shippingAddress!.firstWhere((e) => e.isDefault == true, orElse: () => userModel.shippingAddress!.first); + final defaultAddress = userModel.shippingAddress!.firstWhere( + (e) => e.isDefault == true, + orElse: () => userModel.shippingAddress!.first, + ); Constant.selectedLocation = defaultAddress; Get.offAll(() => const ServiceListScreen()); diff --git a/lib/controllers/parcel_coupon_controller.dart b/lib/controllers/parcel_coupon_controller.dart index 89da091..fe0c298 100644 --- a/lib/controllers/parcel_coupon_controller.dart +++ b/lib/controllers/parcel_coupon_controller.dart @@ -1,9 +1,8 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; - -class ParcelCouponController extends GetxController{ +import 'package:get/get.dart' hide Trans; +class ParcelCouponController extends GetxController { @override void onInit() { // TODO: implement onInit @@ -11,10 +10,10 @@ class ParcelCouponController extends GetxController{ super.onInit(); } - - void getData(){ + void getData() { getCouponCode(); } + RxBool isLoading = true.obs; RxList cabCouponList = [].obs; @@ -26,4 +25,4 @@ class ParcelCouponController extends GetxController{ print("cabCouponList ${cabCouponList.length}"); isLoading.value = false; } -} \ No newline at end of file +} diff --git a/lib/controllers/parcel_dashboard_controller.dart b/lib/controllers/parcel_dashboard_controller.dart index bc9b6a5..38a274e 100644 --- a/lib/controllers/parcel_dashboard_controller.dart +++ b/lib/controllers/parcel_dashboard_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/screen_ui/multi_vendor_service/profile_screen/profile_s import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/screen_ui/parcel_service/home_parcel_screen.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../screen_ui/parcel_service/my_booking_screen.dart'; class ParcelDashboardController extends GetxController { @@ -15,15 +15,26 @@ class ParcelDashboardController extends GetxController { void onInit() { getTaxList(); if (Constant.walletSetting == false) { - pageList.value = [const HomeParcelScreen(), const MyBookingScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeParcelScreen(), + const MyBookingScreen(), + const ProfileScreen(), + ]; } else { - pageList.value = [const HomeParcelScreen(), const MyBookingScreen(), const WalletScreen(), const ProfileScreen()]; + pageList.value = [ + const HomeParcelScreen(), + const MyBookingScreen(), + const WalletScreen(), + const ProfileScreen(), + ]; } super.onInit(); } Future getTaxList() async { - await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then((value) { + await FireStoreUtils.getTaxList(Constant.sectionConstantModel!.id).then(( + value, + ) { if (value != null) { Constant.taxList = value; } diff --git a/lib/controllers/parcel_my_booking_controller.dart b/lib/controllers/parcel_my_booking_controller.dart index 745472f..742e67c 100644 --- a/lib/controllers/parcel_my_booking_controller.dart +++ b/lib/controllers/parcel_my_booking_controller.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../constant/constant.dart'; import '../models/parcel_order_model.dart'; @@ -15,7 +15,8 @@ class ParcelMyBookingController extends GetxController { RxList parcelOrder = [].obs; RxString selectedTab = "New".obs; - RxList tabTitles = ["New", "In Transit", "Delivered", "Cancelled"].obs; + RxList tabTitles = + ["New", "In Transit", "Delivered", "Cancelled"].obs; StreamSubscription>? _parcelSubscription; @@ -53,16 +54,38 @@ class ParcelMyBookingController extends GetxController { List getOrdersForTab(String tab) { switch (tab) { case "New": - return parcelOrder.where((order) => ["Order Placed"].contains(order.status)).toList(); + return parcelOrder + .where((order) => ["Order Placed"].contains(order.status)) + .toList(); case "In Transit": - return parcelOrder.where((order) => ["Order Accepted", "Driver Accepted", "Driver Pending", "Order Shipped", "In Transit"].contains(order.status)).toList(); + return parcelOrder + .where( + (order) => [ + "Order Accepted", + "Driver Accepted", + "Driver Pending", + "Order Shipped", + "In Transit", + ].contains(order.status), + ) + .toList(); case "Delivered": - return parcelOrder.where((order) => ["Order Completed"].contains(order.status)).toList(); + return parcelOrder + .where((order) => ["Order Completed"].contains(order.status)) + .toList(); case "Cancelled": - return parcelOrder.where((order) => ["Order Rejected", "Order Cancelled", "Driver Rejected"].contains(order.status)).toList(); + return parcelOrder + .where( + (order) => [ + "Order Rejected", + "Order Cancelled", + "Driver Rejected", + ].contains(order.status), + ) + .toList(); default: return []; @@ -70,7 +93,8 @@ class ParcelMyBookingController extends GetxController { } /// Old helper (optional) - List get filteredParcelOrders => getOrdersForTab(selectedTab.value); + List get filteredParcelOrders => + getOrdersForTab(selectedTab.value); String formatDate(Timestamp timestamp) { final dateTime = timestamp.toDate(); @@ -97,10 +121,18 @@ class ParcelMyBookingController extends GetxController { final taxSettings = order.taxSetting ?? []; for (var element in taxSettings) { - totalTax += Constant.calculateTax(amount: (double.parse(order.subTotal.toString()) - double.parse(order.discount.toString())).toString(), taxModel: element); + totalTax += Constant.calculateTax( + amount: + (double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString())) + .toString(), + taxModel: element, + ); } - double subTotal = double.parse(order.subTotal.toString()) - double.parse(order.discount.toString()); + double subTotal = + double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString()); double refundAmount = subTotal + totalTax; WalletTransactionModel walletTransaction = WalletTransactionModel( @@ -122,7 +154,10 @@ class ParcelMyBookingController extends GetxController { await FireStoreUtils.setWalletTransaction(walletTransaction); // Update wallet balance - await FireStoreUtils.updateUserWallet(amount: refundAmount.toString(), userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: refundAmount.toString(), + userId: FireStoreUtils.getCurrentUid(), + ); } ShowToastDialog.showToast("Order cancelled successfully".tr()); diff --git a/lib/controllers/parcel_order_confirmation_controller.dart b/lib/controllers/parcel_order_confirmation_controller.dart index 85f2e1d..abbcef0 100644 --- a/lib/controllers/parcel_order_confirmation_controller.dart +++ b/lib/controllers/parcel_order_confirmation_controller.dart @@ -9,7 +9,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; diff --git a/lib/controllers/parcel_order_details_controller.dart b/lib/controllers/parcel_order_details_controller.dart index 334b4f9..6e9e83b 100644 --- a/lib/controllers/parcel_order_details_controller.dart +++ b/lib/controllers/parcel_order_details_controller.dart @@ -4,7 +4,7 @@ import 'package:customer/models/wallet_transaction_model.dart'; import 'package:customer/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart'; import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../constant/constant.dart'; import '../models/parcel_category.dart'; @@ -45,7 +45,12 @@ class ParcelOrderDetailsController extends GetxController { discount.value = double.parse(parcelOrder.value.discount ?? '0.0'); for (var element in parcelOrder.value.taxSetting!) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } totalAmount.value = (subTotal.value - discount.value) + taxAmount.value; @@ -54,22 +59,32 @@ class ParcelOrderDetailsController extends GetxController { Future fetchDriverDetails() async { if (parcelOrder.value.driverId != null) { - await FireStoreUtils.getUserProfile(parcelOrder.value.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile( + parcelOrder.value.driverId ?? '', + ).then((value) { if (value != null) { driverUser.value = value; } }); - await FireStoreUtils.getReviewsbyID(parcelOrder.value.id.toString()).then((value) { - if (value != null) { - ratingModel.value = value; - } - }); + await FireStoreUtils.getReviewsbyID(parcelOrder.value.id.toString()).then( + (value) { + if (value != null) { + ratingModel.value = value; + } + }, + ); } } void setStatusHistoryFromString(ParcelOrderModel order) { - final steps = ["Order Placed", "Driver Accepted", "Pickup Done", "In Transit", "Delivered"]; + final steps = [ + "Order Placed", + "Driver Accepted", + "Pickup Done", + "In Transit", + "Delivered", + ]; final history = []; @@ -79,7 +94,12 @@ class ParcelOrderDetailsController extends GetxController { for (int i = 0; i < steps.length; i++) { final step = steps[i]; - history.add(ParcelStatus(status: step, time: baseTime.add(Duration(minutes: i * minutesGap)))); + history.add( + ParcelStatus( + status: step, + time: baseTime.add(Duration(minutes: i * minutesGap)), + ), + ); if (step == order.status) break; } @@ -109,7 +129,10 @@ class ParcelOrderDetailsController extends GetxController { await FireStoreUtils.setWalletTransaction(walletTransaction); // Update wallet balance - await FireStoreUtils.updateUserWallet(amount: totalAmount.value.toString(), userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: totalAmount.value.toString(), + userId: FireStoreUtils.getCurrentUid(), + ); } await FireStoreUtils.parcelOrderPlace(parcelOrder.value); @@ -132,7 +155,12 @@ class ParcelOrderDetailsController extends GetxController { ParcelCategory? getSelectedCategory() { try { - return parcelCategory.firstWhere((cat) => cat.title?.toLowerCase().trim() == parcelOrder.value.parcelType?.toLowerCase().trim(), orElse: () => ParcelCategory()); + return parcelCategory.firstWhere( + (cat) => + cat.title?.toLowerCase().trim() == + parcelOrder.value.parcelType?.toLowerCase().trim(), + orElse: () => ParcelCategory(), + ); } catch (e) { return null; } diff --git a/lib/controllers/parcel_review_controller.dart b/lib/controllers/parcel_review_controller.dart index 58691f8..2ad0958 100644 --- a/lib/controllers/parcel_review_controller.dart +++ b/lib/controllers/parcel_review_controller.dart @@ -2,7 +2,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:customer/models/parcel_order_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/rating_model.dart'; import '../models/user_model.dart'; import '../service/fire_store_utils.dart'; @@ -47,12 +47,17 @@ class ParcelReviewController extends GetxController { } }); - await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then(( + value, + ) { if (value != null) { driverUser.value = value; - final int userReviewsCount = int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? 0; - final int userReviewsSum = int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; + final int userReviewsCount = + int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? + 0; + final int userReviewsSum = + int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; if (ratingModel.value != null) { final int oldRating = ratingModel.value?.rating?.toInt() ?? 0; @@ -77,7 +82,9 @@ class ParcelReviewController extends GetxController { ShowToastDialog.showLoader("Submit in...".tr()); - final user = await FireStoreUtils.getUserProfile(order.value?.driverId ?? ''); + final user = await FireStoreUtils.getUserProfile( + order.value?.driverId ?? '', + ); if (user != null) { user.reviewsCount = (futureCount.value + 1).toString(); @@ -94,7 +101,8 @@ class ParcelReviewController extends GetxController { driverId: ratingModel.value!.driverId, customerId: ratingModel.value!.customerId, vendorId: ratingModel.value?.vendorId, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); @@ -113,7 +121,8 @@ class ParcelReviewController extends GetxController { orderId: order.value?.id, driverId: order.value?.driverId.toString(), customerId: Constant.userModel?.id, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); diff --git a/lib/controllers/provider_controller.dart b/lib/controllers/provider_controller.dart index b10e21d..ed6379e 100644 --- a/lib/controllers/provider_controller.dart +++ b/lib/controllers/provider_controller.dart @@ -1,5 +1,5 @@ import 'package:customer/controllers/on_demand_home_controller.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/provider_serivce_model.dart'; import '../models/user_model.dart'; import '../service/fire_store_utils.dart'; @@ -10,7 +10,8 @@ class ProviderController extends GetxController { RxBool isLoading = true.obs; late final String providerId; - Rx onDemandHomeController = Get.put(OnDemandHomeController()).obs; + Rx onDemandHomeController = + Get.put(OnDemandHomeController()).obs; @override void onInit() { @@ -24,7 +25,9 @@ class ProviderController extends GetxController { } void getProvider() async { - FireStoreUtils.getProviderServiceByProviderId(providerId: providerId).then((catValue) { + FireStoreUtils.getProviderServiceByProviderId(providerId: providerId).then(( + catValue, + ) { providerList.value = catValue; }); diff --git a/lib/controllers/rate_product_controller.dart b/lib/controllers/rate_product_controller.dart index 61086a1..ece8c88 100644 --- a/lib/controllers/rate_product_controller.dart +++ b/lib/controllers/rate_product_controller.dart @@ -12,7 +12,7 @@ import '../models/review_attribute_model.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:image_picker/image_picker.dart'; import '../themes/show_toast_dialog.dart'; @@ -35,7 +35,8 @@ class RateProductController extends GetxController { Rx vendorModel = VendorModel().obs; Rx vendorCategoryModel = VendorCategoryModel().obs; - RxList reviewAttributeList = [].obs; + RxList reviewAttributeList = + [].obs; RxDouble ratings = 0.0.obs; @@ -54,7 +55,10 @@ class RateProductController extends GetxController { orderModel.value = argumentData['orderModel']; productId.value = argumentData['productId']; - await FireStoreUtils.getOrderReviewsByID(orderModel.value.id.toString(), productId.value).then((value) { + await FireStoreUtils.getOrderReviewsByID( + orderModel.value.id.toString(), + productId.value, + ).then((value) { if (value != null) { ratingModel.value = value; ratings.value = value.rating ?? 0.0; @@ -64,23 +68,33 @@ class RateProductController extends GetxController { } }); - await FireStoreUtils.getProductById(productId.value.split('~').first).then((value) { + await FireStoreUtils.getProductById( + productId.value.split('~').first, + ).then((value) { if (value != null) { productModel.value = value; - if (ratingModel.value.id != null && ratingModel.value.id!.isNotEmpty) { + if (ratingModel.value.id != null && + ratingModel.value.id!.isNotEmpty) { productReviewCount.value = value.reviewsCount! - 1; productReviewSum.value = value.reviewsSum! - ratings.value; if (value.reviewAttributes != null) { value.reviewAttributes!.forEach((key, value) { - ReviewsAttribute reviewsAttributeModel = ReviewsAttribute.fromJson(value); - reviewsAttributeModel.reviewsCount = reviewsAttributeModel.reviewsCount! - 1; - reviewsAttributeModel.reviewsSum = reviewsAttributeModel.reviewsSum! - reviewAttribute[key]; - reviewProductAttributes.addEntries([MapEntry(key, reviewsAttributeModel.toJson())]); + ReviewsAttribute reviewsAttributeModel = + ReviewsAttribute.fromJson(value); + reviewsAttributeModel.reviewsCount = + reviewsAttributeModel.reviewsCount! - 1; + reviewsAttributeModel.reviewsSum = + reviewsAttributeModel.reviewsSum! - reviewAttribute[key]; + reviewProductAttributes.addEntries([ + MapEntry(key, reviewsAttributeModel.toJson()), + ]); }); } } else { - productReviewCount.value = double.parse(value.reviewsCount.toString()); + productReviewCount.value = double.parse( + value.reviewsCount.toString(), + ); productReviewSum.value = double.parse(value.reviewsSum.toString()); if (value.reviewAttributes != null) { reviewProductAttributes.value = value.reviewAttributes!; @@ -89,24 +103,33 @@ class RateProductController extends GetxController { } }); - await FireStoreUtils.getVendorById(productModel.value.vendorID.toString()).then((value) { + await FireStoreUtils.getVendorById( + productModel.value.vendorID.toString(), + ).then((value) { if (value != null) { vendorModel.value = value; - if (ratingModel.value.id != null && ratingModel.value.id!.isNotEmpty) { + if (ratingModel.value.id != null && + ratingModel.value.id!.isNotEmpty) { vendorReviewCount.value = value.reviewsCount! - 1; vendorReviewSum.value = value.reviewsSum! - ratings.value; } else { - vendorReviewCount.value = double.parse(value.reviewsCount.toString()); + vendorReviewCount.value = double.parse( + value.reviewsCount.toString(), + ); vendorReviewSum.value = double.parse(value.reviewsSum.toString()); } } }); - await FireStoreUtils.getVendorCategoryByCategoryId(productModel.value.categoryID.toString()).then((value) async { + await FireStoreUtils.getVendorCategoryByCategoryId( + productModel.value.categoryID.toString(), + ).then((value) async { if (value != null) { vendorCategoryModel.value = value; for (var element in vendorCategoryModel.value.reviewAttributes!) { - await FireStoreUtils.getVendorReviewAttribute(element).then((value) { + await FireStoreUtils.getVendorReviewAttribute(element).then(( + value, + ) { reviewAttributeList.add(value!); }); } @@ -129,21 +152,36 @@ class RateProductController extends GetxController { if (reviewProductAttributes.isEmpty) { reviewAttribute.forEach((key, value) { - ReviewsAttribute reviewsAttributeModel = ReviewsAttribute(reviewsCount: 1, reviewsSum: value); - reviewProductAttributes.addEntries([MapEntry(key, reviewsAttributeModel.toJson())]); + ReviewsAttribute reviewsAttributeModel = ReviewsAttribute( + reviewsCount: 1, + reviewsSum: value, + ); + reviewProductAttributes.addEntries([ + MapEntry(key, reviewsAttributeModel.toJson()), + ]); }); } else { reviewProductAttributes.forEach((key, value) { - ReviewsAttribute reviewsAttributeModel = ReviewsAttribute.fromJson(value); - reviewsAttributeModel.reviewsCount = reviewsAttributeModel.reviewsCount! + 1; - reviewsAttributeModel.reviewsSum = reviewsAttributeModel.reviewsSum! + reviewAttribute[key]; - reviewProductAttributes.addEntries([MapEntry(key, reviewsAttributeModel.toJson())]); + ReviewsAttribute reviewsAttributeModel = ReviewsAttribute.fromJson( + value, + ); + reviewsAttributeModel.reviewsCount = + reviewsAttributeModel.reviewsCount! + 1; + reviewsAttributeModel.reviewsSum = + reviewsAttributeModel.reviewsSum! + reviewAttribute[key]; + reviewProductAttributes.addEntries([ + MapEntry(key, reviewsAttributeModel.toJson()), + ]); }); } for (int i = 0; i < images.length; i++) { if (images[i].runtimeType == XFile) { - String url = await Constant.uploadUserImageToFireStorage(File(images[i].path), "profileImage/${FireStoreUtils.getCurrentUid()}", File(images[i].path).path.split('/').last); + String url = await Constant.uploadUserImageToFireStorage( + File(images[i].path), + "profileImage/${FireStoreUtils.getCurrentUid()}", + File(images[i].path).path.split('/').last, + ); images.removeAt(i); images.insert(i, url); } @@ -155,7 +193,10 @@ class RateProductController extends GetxController { photos: images, rating: ratings.value, customerId: FireStoreUtils.getCurrentUid(), - id: ratingModel.value.id != null && ratingModel.value.id!.isNotEmpty ? ratingModel.value.id : Constant.getUuid(), + id: + ratingModel.value.id != null && ratingModel.value.id!.isNotEmpty + ? ratingModel.value.id + : Constant.getUuid(), orderId: orderModel.value.id, vendorId: productModel.value.vendorID, createdAt: Timestamp.now(), diff --git a/lib/controllers/redeem_gift_card_controller.dart b/lib/controllers/redeem_gift_card_controller.dart index d445e2f..8332496 100644 --- a/lib/controllers/redeem_gift_card_controller.dart +++ b/lib/controllers/redeem_gift_card_controller.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class RedeemGiftCardController extends GetxController { Rx giftCodeController = TextEditingController().obs; diff --git a/lib/controllers/refer_friend_controller.dart b/lib/controllers/refer_friend_controller.dart index 8b9cd87..66c3f7e 100644 --- a/lib/controllers/refer_friend_controller.dart +++ b/lib/controllers/refer_friend_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/models/referral_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ReferFriendController extends GetxController { Rx referralModel = ReferralModel().obs; diff --git a/lib/controllers/rental_conformation_controller.dart b/lib/controllers/rental_conformation_controller.dart index a0bf823..49f838e 100644 --- a/lib/controllers/rental_conformation_controller.dart +++ b/lib/controllers/rental_conformation_controller.dart @@ -7,8 +7,7 @@ import 'package:customer/service/fire_store_utils.dart'; import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../screen_ui/rental_service/rental_dashboard_screen.dart'; import 'cab_rental_dashboard_controllers.dart'; @@ -27,7 +26,8 @@ class RentalConformationController extends GetxController { void getArguments() { final args = Get.arguments; - if (args.containsKey('rentalOrderModel') && args['rentalOrderModel'] is RentalOrderModel) { + if (args.containsKey('rentalOrderModel') && + args['rentalOrderModel'] is RentalOrderModel) { rentalOrderModel.value = args['rentalOrderModel'] as RentalOrderModel; calculateAmount(); } else { @@ -48,12 +48,21 @@ class RentalConformationController extends GetxController { taxAmount.value = 0.0; totalAmount.value = 0.0; - subTotal.value = double.tryParse(rentalOrderModel.value.subTotal ?? '0') ?? 0.0; + subTotal.value = + double.tryParse(rentalOrderModel.value.subTotal ?? '0') ?? 0.0; if (selectedCouponModel.value.id != null) { - discount.value = Constant.calculateDiscount(amount: subTotal.value.toString(), offerModel: selectedCouponModel.value); + discount.value = Constant.calculateDiscount( + amount: subTotal.value.toString(), + offerModel: selectedCouponModel.value, + ); } for (var element in rentalOrderModel.value.taxSetting ?? []) { - taxAmount.value = (taxAmount.value + Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element)); + taxAmount.value = + (taxAmount.value + + Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + )); } totalAmount.value = subTotal.value - discount.value + taxAmount.value; @@ -77,12 +86,17 @@ class RentalConformationController extends GetxController { rentalOrderModel.value.couponCode = selectedCouponModel.value.code; rentalOrderModel.value.couponId = selectedCouponModel.value.id; rentalOrderModel.value.subTotal = subTotal.value.toString(); - rentalOrderModel.value.otpCode = (maths.Random().nextInt(9000) + 1000).toString(); - await FireStoreUtils.rentalOrderPlace(rentalOrderModel.value).then((value) async { + rentalOrderModel.value.otpCode = + (maths.Random().nextInt(9000) + 1000).toString(); + await FireStoreUtils.rentalOrderPlace(rentalOrderModel.value).then(( + value, + ) async { ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Order placed successfully".tr()); Get.offAll(const RentalDashboardScreen()); - CabRentalDashboardControllers controller = Get.put(CabRentalDashboardControllers()); + CabRentalDashboardControllers controller = Get.put( + CabRentalDashboardControllers(), + ); controller.selectedIndex.value = 1; // Get.back(); }); diff --git a/lib/controllers/rental_coupon_controller.dart b/lib/controllers/rental_coupon_controller.dart index 9f4b303..4cb1292 100644 --- a/lib/controllers/rental_coupon_controller.dart +++ b/lib/controllers/rental_coupon_controller.dart @@ -1,9 +1,8 @@ import 'package:customer/models/coupon_model.dart'; import 'package:customer/service/fire_store_utils.dart'; -import 'package:get/get.dart'; - -class RentalCouponController extends GetxController{ +import 'package:get/get.dart' hide Trans; +class RentalCouponController extends GetxController { @override void onInit() { // TODO: implement onInit @@ -11,10 +10,10 @@ class RentalCouponController extends GetxController{ super.onInit(); } - - void getData(){ + void getData() { getCouponCode(); } + RxBool isLoading = true.obs; RxList cabCouponList = [].obs; @@ -25,4 +24,4 @@ class RentalCouponController extends GetxController{ print("cabCouponList ${cabCouponList.length}"); isLoading.value = false; } -} \ No newline at end of file +} diff --git a/lib/controllers/rental_home_controller.dart b/lib/controllers/rental_home_controller.dart index c7a3a36..87b8181 100644 --- a/lib/controllers/rental_home_controller.dart +++ b/lib/controllers/rental_home_controller.dart @@ -10,7 +10,7 @@ import 'package:customer/widget/geoflutterfire/src/geoflutterfire.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart' as latlong; import '../constant/constant.dart'; import '../models/payment_model/cod_setting_model.dart'; @@ -38,7 +38,8 @@ class RentalHomeController extends GetxController { RxBool isLoading = false.obs; // Location input - final Rx sourceTextEditController = TextEditingController().obs; + final Rx sourceTextEditController = + TextEditingController().obs; // Selected date Rx selectedDate = DateTime.now().obs; @@ -74,11 +75,20 @@ class RentalHomeController extends GetxController { Constant.currentLocation = position; // Set default coordinates for Google or OSM - departureLatLong.value = gmaps.LatLng(position.latitude, position.longitude); - departureLatLongOsm.value = latlong.LatLng(position.latitude, position.longitude); + departureLatLong.value = gmaps.LatLng( + position.latitude, + position.longitude, + ); + departureLatLongOsm.value = latlong.LatLng( + position.latitude, + position.longitude, + ); // Get readable address - String address = await Utils.getAddressFromCoordinates(position.latitude, position.longitude); + String address = await Utils.getAddressFromCoordinates( + position.latitude, + position.longitude, + ); sourceTextEditController.value.text = address; } } catch (e) { @@ -102,7 +112,12 @@ class RentalHomeController extends GetxController { /// Date Picker Future pickDate(BuildContext context) async { - final DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate.value, firstDate: DateTime.now(), lastDate: DateTime(2100)); + final DateTime? picked = await showDatePicker( + context: context, + initialDate: selectedDate.value, + firstDate: DateTime.now(), + lastDate: DateTime(2100), + ); if (picked != null) { selectedDate.value = picked; @@ -110,7 +125,9 @@ class RentalHomeController extends GetxController { } Future getRentalPackage() async { - await FireStoreUtils.getRentalPackage(selectedVehicleType.value!.id.toString()).then((value) { + await FireStoreUtils.getRentalPackage( + selectedVehicleType.value!.id.toString(), + ).then((value) { rentalPackages.value = value; if (rentalPackages.isNotEmpty) { selectedPackage.value = rentalPackages[0]; @@ -120,8 +137,14 @@ class RentalHomeController extends GetxController { void completeOrder() { DestinationLocation sourceLocation = DestinationLocation( - latitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.latitude : departureLatLong.value.latitude, - longitude: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value.longitude : departureLatLong.value.longitude, + latitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.latitude + : departureLatLong.value.latitude, + longitude: + Constant.selectedMapType == 'osm' + ? departureLatLongOsm.value.longitude + : departureLatLong.value.longitude, ); print("=====>"); @@ -144,18 +167,35 @@ class RentalHomeController extends GetxController { rentalOrderModel.taxSetting = Constant.taxList; rentalOrderModel.createdAt = Timestamp.now(); rentalOrderModel.sourceLocation = sourceLocation; - rentalOrderModel.adminCommission = Constant.sectionConstantModel!.adminCommision!.amount; - rentalOrderModel.adminCommissionType = Constant.sectionConstantModel!.adminCommision!.commissionType; + rentalOrderModel.adminCommission = + Constant.sectionConstantModel!.adminCommision!.amount; + rentalOrderModel.adminCommissionType = + Constant.sectionConstantModel!.adminCommision!.commissionType; rentalOrderModel.sourcePoint = G( - geopoint: GeoPoint(sourceLocation.latitude ?? 0.0, sourceLocation.longitude ?? 0.0), - geohash: Geoflutterfire().point(latitude: sourceLocation.latitude ?? 0.0, longitude: sourceLocation.longitude ?? 0.0).hash, + geopoint: GeoPoint( + sourceLocation.latitude ?? 0.0, + sourceLocation.longitude ?? 0.0, + ), + geohash: + Geoflutterfire() + .point( + latitude: sourceLocation.latitude ?? 0.0, + longitude: sourceLocation.longitude ?? 0.0, + ) + .hash, + ); + rentalOrderModel.zoneId = Constant.getZoneId( + sourceLocation.latitude ?? 0.0, + sourceLocation.longitude ?? 0.0, ); - rentalOrderModel.zoneId = Constant.getZoneId(sourceLocation.latitude ?? 0.0, sourceLocation.longitude ?? 0.0); log(rentalOrderModel.toJson().toString()); Get.back(); Get.back(); - Get.to(() => RentalConformationScreen(), arguments: {"rentalOrderModel": rentalOrderModel}); + Get.to( + () => RentalConformationScreen(), + arguments: {"rentalOrderModel": rentalOrderModel}, + ); } void setDepartureMarker(double lat, double lng) { @@ -194,19 +234,45 @@ class RentalHomeController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; diff --git a/lib/controllers/rental_order_details_controller.dart b/lib/controllers/rental_order_details_controller.dart index e51f7af..69bd57c 100644 --- a/lib/controllers/rental_order_details_controller.dart +++ b/lib/controllers/rental_order_details_controller.dart @@ -39,7 +39,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:uuid/uuid.dart'; @@ -84,13 +84,17 @@ class RentalOrderDetailsController extends GetxController { Future fetchDriverDetails() async { if (order.value.driverId != null) { - await FireStoreUtils.getUserProfile(order.value.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile(order.value.driverId ?? '').then(( + value, + ) { if (value != null) { driverUser.value = value; } }); - await FireStoreUtils.getReviewsbyID(order.value.id.toString()).then((value) { + await FireStoreUtils.getReviewsbyID(order.value.id.toString()).then(( + value, + ) { if (value != null) { ratingModel.value = value; } @@ -100,9 +104,15 @@ class RentalOrderDetailsController extends GetxController { String getExtraKm() { try { - final double start = double.tryParse(order.value.startKitoMetersReading ?? '0') ?? 0.0; - final double end = double.tryParse(order.value.endKitoMetersReading ?? '0') ?? 0.0; - final double included = double.tryParse(order.value.rentalPackageModel?.includedDistance?.toString() ?? '0') ?? 0.0; + final double start = + double.tryParse(order.value.startKitoMetersReading ?? '0') ?? 0.0; + final double end = + double.tryParse(order.value.endKitoMetersReading ?? '0') ?? 0.0; + final double included = + double.tryParse( + order.value.rentalPackageModel?.includedDistance?.toString() ?? '0', + ) ?? + 0.0; // Calculate extra km safely final double extra = (end - start - included); @@ -117,8 +127,10 @@ class RentalOrderDetailsController extends GetxController { ///Safe calculation after order is loaded void calculateTotalAmount() { try { - subTotal.value = double.tryParse(order.value.subTotal?.toString() ?? "0") ?? 0.0; - discount.value = double.tryParse(order.value.discount?.toString() ?? "0") ?? 0.0; + subTotal.value = + double.tryParse(order.value.subTotal?.toString() ?? "0") ?? 0.0; + discount.value = + double.tryParse(order.value.discount?.toString() ?? "0") ?? 0.0; taxAmount.value = 0.0; if (order.value.endTime != null) { @@ -128,12 +140,23 @@ class RentalOrderDetailsController extends GetxController { // Total rented minutes int totalMinutes = end.difference(start).inMinutes; - int includedMinutes = (int.tryParse(order.value.rentalPackageModel?.includedHours.toString() ?? "0") ?? 0) * 60; + int includedMinutes = + (int.tryParse( + order.value.rentalPackageModel?.includedHours.toString() ?? + "0", + ) ?? + 0) * + 60; if (totalMinutes > includedMinutes) { int extraMinutes = totalMinutes - includedMinutes; - double minuteFare = double.tryParse(order.value.rentalPackageModel?.extraMinuteFare?.toString() ?? "0") ?? 0.0; + double minuteFare = + double.tryParse( + order.value.rentalPackageModel?.extraMinuteFare?.toString() ?? + "0", + ) ?? + 0.0; extraMinutesCharge.value = extraMinutes * minuteFare; } else { @@ -141,24 +164,47 @@ class RentalOrderDetailsController extends GetxController { } } - if (order.value.startKitoMetersReading != null && order.value.endKitoMetersReading != null) { - double startKm = double.tryParse(order.value.startKitoMetersReading?.toString() ?? "0") ?? 0.0; - double endKm = double.tryParse(order.value.endKitoMetersReading?.toString() ?? "0") ?? 0.0; + if (order.value.startKitoMetersReading != null && + order.value.endKitoMetersReading != null) { + double startKm = + double.tryParse( + order.value.startKitoMetersReading?.toString() ?? "0", + ) ?? + 0.0; + double endKm = + double.tryParse( + order.value.endKitoMetersReading?.toString() ?? "0", + ) ?? + 0.0; if (endKm > startKm) { double totalKm = endKm - startKm; - if (totalKm > double.parse(order.value.rentalPackageModel!.includedDistance!)) { - totalKm = totalKm - double.parse(order.value.rentalPackageModel!.includedDistance!); - double extraKmRate = double.tryParse(order.value.rentalPackageModel?.extraKmFare?.toString() ?? "0") ?? 0.0; + if (totalKm > + double.parse(order.value.rentalPackageModel!.includedDistance!)) { + totalKm = + totalKm - + double.parse(order.value.rentalPackageModel!.includedDistance!); + double extraKmRate = + double.tryParse( + order.value.rentalPackageModel?.extraKmFare?.toString() ?? + "0", + ) ?? + 0.0; extraKilometerCharge.value = totalKm * extraKmRate; } } } - subTotal.value = subTotal.value + extraKilometerCharge.value + extraMinutesCharge.value; + subTotal.value = + subTotal.value + + extraKilometerCharge.value + + extraMinutesCharge.value; if (order.value.taxSetting != null) { for (var element in order.value.taxSetting!) { - taxAmount.value += Constant.calculateTax(amount: (subTotal.value - discount.value).toString(), taxModel: element); + taxAmount.value += Constant.calculateTax( + amount: (subTotal.value - discount.value).toString(), + taxModel: element, + ); } } @@ -194,9 +240,14 @@ class RentalOrderDetailsController extends GetxController { serviceType: Constant.parcelServiceType, ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: "-${totalAmount.toString()}", userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: "-${totalAmount.toString()}", + userId: FireStoreUtils.getCurrentUid(), + ); } }); } @@ -209,7 +260,10 @@ class RentalOrderDetailsController extends GetxController { } } - Future cancelRentalRequest(RentalOrderModel order, {List? taxList}) async { + Future cancelRentalRequest( + RentalOrderModel order, { + List? taxList, + }) async { try { isLoading.value = true; @@ -221,11 +275,19 @@ class RentalOrderDetailsController extends GetxController { if (taxList != null) { for (var element in taxList) { - totalTax += Constant.calculateTax(amount: (double.parse(order.subTotal.toString()) - double.parse(order.discount.toString())).toString(), taxModel: element); + totalTax += Constant.calculateTax( + amount: + (double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString())) + .toString(), + taxModel: element, + ); } } - double subTotal = double.parse(order.subTotal.toString()) - double.parse(order.discount.toString()); + double subTotal = + double.parse(order.subTotal.toString()) - + double.parse(order.discount.toString()); double refundAmount = subTotal + totalTax; WalletTransactionModel walletTransaction = WalletTransactionModel( @@ -244,7 +306,10 @@ class RentalOrderDetailsController extends GetxController { ); await FireStoreUtils.setWalletTransaction(walletTransaction); - await FireStoreUtils.updateUserWallet(amount: refundAmount.toString(), userId: FireStoreUtils.getCurrentUid()); + await FireStoreUtils.updateUserWallet( + amount: refundAmount.toString(), + userId: FireStoreUtils.getCurrentUid(), + ); } ShowToastDialog.showToast("Booking cancelled successfully".tr()); Get.back(); @@ -272,19 +337,45 @@ class RentalOrderDetailsController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - paytmModel.value = PaytmModel.fromJson(jsonDecode(Preferences.getString(Preferences.paytmSettings))); - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(jsonDecode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); - walletSettingModel.value = WalletSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.walletSettings))); - cashOnDeliverySettingModel.value = CodSettingModel.fromJson(jsonDecode(Preferences.getString(Preferences.codSettings))); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + paytmModel.value = PaytmModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paytmSettings)), + ); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + jsonDecode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); + walletSettingModel.value = WalletSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.walletSettings)), + ); + cashOnDeliverySettingModel.value = CodSettingModel.fromJson( + jsonDecode(Preferences.getString(Preferences.codSettings)), + ); if (walletSettingModel.value.isEnabled == true) { selectedPaymentMethod.value = PaymentGateway.wallet.name; @@ -326,20 +417,32 @@ class RentalOrderDetailsController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -385,7 +488,10 @@ class RentalOrderDetailsController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -395,8 +501,14 @@ class RentalOrderDetailsController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -409,12 +521,20 @@ class RentalOrderDetailsController extends GetxController { }, ], "payer": {"email": Constant.userModel!.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, "auto_return": "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -497,15 +617,23 @@ class RentalOrderDetailsController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -515,17 +643,23 @@ class RentalOrderDetailsController extends GetxController { "payment_options": "ussd, card, barter, payattitude", "customer": { "email": Constant.userModel!.email.toString(), - "phonenumber": Constant.userModel!.phoneNumber, // Add a real phone number + "phonenumber": + Constant.userModel!.phoneNumber, // Add a real phone number "name": Constant.userModel!.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -554,8 +688,14 @@ class RentalOrderDetailsController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: Constant.userModel!).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: Constant.userModel!, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -594,7 +734,14 @@ class RentalOrderDetailsController extends GetxController { // }); } - Future startTransaction(context, {required String txnTokenBy, required orderId, required double amount, required callBackURL, required isStaging}) async { + Future startTransaction( + context, { + required String txnTokenBy, + required orderId, + required double amount, + required callBackURL, + required isStaging, + }) async { // try { // var response = AllInOneSdk.startTransaction( // paytmModel.value.paytmMID.toString(), @@ -630,24 +777,38 @@ class RentalOrderDetailsController extends GetxController { // } } - Future verifyCheckSum({required String checkSum, required double amount, required orderId}) async { + Future verifyCheckSum({ + required String checkSum, + required double amount, + required orderId, + }) async { String getChecksum = "${Constant.globalUrl}payments/validatechecksum"; final response = await http.post( Uri.parse(getChecksum), headers: {}, - body: {"mid": paytmModel.value.paytmMID.toString(), "order_id": orderId, "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), "checksum_value": checkSum}, + body: { + "mid": paytmModel.value.paytmMID.toString(), + "order_id": orderId, + "key_secret": paytmModel.value.pAYTMMERCHANTKEY.toString(), + "checksum_value": checkSum, + }, ); final data = jsonDecode(response.body); return data['status']; } - Future initiatePayment({required double amount, required orderId}) async { + Future initiatePayment({ + required double amount, + required orderId, + }) async { String initiateURL = "${Constant.globalUrl}payments/initiatepaytmpayment"; String callback = ""; if (paytmModel.value.isSandboxEnabled == true) { - callback = "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } else { - callback = "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; + callback = + "${callback}https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=$orderId"; } final response = await http.post( Uri.parse(initiateURL), @@ -665,9 +826,12 @@ class RentalOrderDetailsController extends GetxController { ); log(response.body); final data = jsonDecode(response.body); - if (data["body"]["txnToken"] == null || data["body"]["txnToken"].toString().isEmpty) { + if (data["body"]["txnToken"] == null || + data["body"]["txnToken"].toString().isEmpty) { Get.back(); - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); } return GetPaymentTxtTokenModel.fromJson(data); } @@ -685,7 +849,10 @@ class RentalOrderDetailsController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': Constant.userModel!.phoneNumber, 'email': Constant.userModel!.email}, + 'prefill': { + 'contact': Constant.userModel!.phoneNumber, + 'email': Constant.userModel!.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -720,7 +887,10 @@ class RentalOrderDetailsController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -738,15 +908,30 @@ class RentalOrderDetailsController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -754,7 +939,9 @@ class RentalOrderDetailsController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -771,13 +958,30 @@ class RentalOrderDetailsController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -789,13 +993,22 @@ class RentalOrderDetailsController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth!}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -806,17 +1019,32 @@ class RentalOrderDetailsController extends GetxController { accessToken = responseData['access_token']; // ignore: use_build_context_synchronously - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; - String apiUrl = orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -831,7 +1059,11 @@ class RentalOrderDetailsController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -845,7 +1077,9 @@ class RentalOrderDetailsController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -861,7 +1095,13 @@ class RentalOrderDetailsController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); completeOrder(); @@ -877,7 +1117,9 @@ class RentalOrderDetailsController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -890,7 +1132,11 @@ class RentalOrderDetailsController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/controllers/rental_review_controller.dart b/lib/controllers/rental_review_controller.dart index 1314702..88d06c3 100644 --- a/lib/controllers/rental_review_controller.dart +++ b/lib/controllers/rental_review_controller.dart @@ -1,7 +1,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../constant/collection_name.dart'; import '../models/rating_model.dart'; import '../models/rental_order_model.dart'; @@ -48,12 +48,17 @@ class RentalReviewController extends GetxController { } }); - await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then((value) { + await FireStoreUtils.getUserProfile(order.value?.driverId ?? '').then(( + value, + ) { if (value != null) { driverUser.value = value; - final int userReviewsCount = int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? 0; - final int userReviewsSum = int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; + final int userReviewsCount = + int.tryParse(driverUser.value!.reviewsCount?.toString() ?? "0") ?? + 0; + final int userReviewsSum = + int.tryParse(driverUser.value!.reviewsSum?.toString() ?? "0") ?? 0; if (ratingModel.value != null) { final int oldRating = ratingModel.value?.rating?.toInt() ?? 0; @@ -78,7 +83,9 @@ class RentalReviewController extends GetxController { ShowToastDialog.showLoader("Submit in...".tr()); - final user = await FireStoreUtils.getUserProfile(order.value?.driverId ?? ''); + final user = await FireStoreUtils.getUserProfile( + order.value?.driverId ?? '', + ); if (user != null) { user.reviewsCount = (futureCount.value + 1).toString(); @@ -95,7 +102,8 @@ class RentalReviewController extends GetxController { driverId: ratingModel.value!.driverId, customerId: ratingModel.value!.customerId, vendorId: ratingModel.value?.vendorId, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); @@ -106,7 +114,8 @@ class RentalReviewController extends GetxController { } } else { /// New review - final docRef = FireStoreUtils.fireStore.collection(CollectionName.itemsReview).doc(); + final docRef = + FireStoreUtils.fireStore.collection(CollectionName.itemsReview).doc(); final newRating = RatingModel( id: docRef.id, comment: comment.value.text, @@ -115,7 +124,8 @@ class RentalReviewController extends GetxController { orderId: order.value?.id, driverId: order.value?.driverId.toString(), customerId: Constant.userModel?.id, - uname: "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", + uname: + "${Constant.userModel?.firstName ?? ''} ${Constant.userModel?.lastName ?? ''}", profile: Constant.userModel?.profilePictureURL, createdAt: Timestamp.now(), ); diff --git a/lib/controllers/restaurant_details_controller.dart b/lib/controllers/restaurant_details_controller.dart index 7901954..dcc56ac 100644 --- a/lib/controllers/restaurant_details_controller.dart +++ b/lib/controllers/restaurant_details_controller.dart @@ -13,11 +13,12 @@ import '../models/attributes_model.dart'; import '../service/cart_provider.dart'; import '../service/fire_store_utils.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; class RestaurantDetailsController extends GetxController { - Rx searchEditingController = TextEditingController().obs; + Rx searchEditingController = + TextEditingController().obs; RxBool isLoading = true.obs; Rx pageController = PageController().obs; @@ -44,7 +45,8 @@ class RestaurantDetailsController extends GetxController { } void animateSlider() { - if (vendorModel.value.photos != null && vendorModel.value.photos!.isNotEmpty) { + if (vendorModel.value.photos != null && + vendorModel.value.photos!.isNotEmpty) { Timer.periodic(const Duration(seconds: 2), (Timer timer) { if (currentPage < vendorModel.value.photos!.length - 1) { currentPage++; @@ -53,7 +55,11 @@ class RestaurantDetailsController extends GetxController { } if (pageController.value.hasClients) { - pageController.value.animateToPage(currentPage.value, duration: const Duration(milliseconds: 300), curve: Curves.easeIn); + pageController.value.animateToPage( + currentPage.value, + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); } }); } @@ -86,14 +92,25 @@ class RestaurantDetailsController extends GetxController { RxList brandList = [].obs; Future getProduct() async { - await FireStoreUtils.getProductByVendorId(vendorModel.value.id.toString()).then((value) { - if ((Constant.isSubscriptionModelApplied == true || vendorModel.value.adminCommission?.isEnabled == true) && vendorModel.value.subscriptionPlan != null) { + await FireStoreUtils.getProductByVendorId( + vendorModel.value.id.toString(), + ).then((value) { + if ((Constant.isSubscriptionModelApplied == true || + vendorModel.value.adminCommission?.isEnabled == true) && + vendorModel.value.subscriptionPlan != null) { if (vendorModel.value.subscriptionPlan?.itemLimit == '-1') { allProductList.value = value; productList.value = value; } else { int selectedProduct = - value.length < int.parse(vendorModel.value.subscriptionPlan?.itemLimit ?? '0') ? (value.isEmpty ? 0 : (value.length)) : int.parse(vendorModel.value.subscriptionPlan?.itemLimit ?? '0'); + value.length < + int.parse( + vendorModel.value.subscriptionPlan?.itemLimit ?? '0', + ) + ? (value.isEmpty ? 0 : (value.length)) + : int.parse( + vendorModel.value.subscriptionPlan?.itemLimit ?? '0', + ); allProductList.value = value.sublist(0, selectedProduct); productList.value = value.sublist(0, selectedProduct); } @@ -104,7 +121,9 @@ class RestaurantDetailsController extends GetxController { }); for (var element in productList) { - await FireStoreUtils.getVendorCategoryById(element.categoryID.toString()).then((value) { + await FireStoreUtils.getVendorCategoryById( + element.categoryID.toString(), + ).then((value) { if (value != null) { vendorCategoryList.add(value); } @@ -116,7 +135,10 @@ class RestaurantDetailsController extends GetxController { }); var seen = {}; - vendorCategoryList.value = vendorCategoryList.where((element) => seen.add(element.id.toString())).toList(); + vendorCategoryList.value = + vendorCategoryList + .where((element) => seen.add(element.id.toString())) + .toList(); } void searchProduct(String name) { @@ -126,25 +148,42 @@ class RestaurantDetailsController extends GetxController { } else { isVag.value = false; isNonVag.value = false; - productList.value = allProductList.where((p0) => p0.name!.toLowerCase().contains(name.toLowerCase())).toList(); + productList.value = + allProductList + .where( + (p0) => p0.name!.toLowerCase().contains(name.toLowerCase()), + ) + .toList(); } update(); } void filterRecord() { if (isVag.value == true && isNonVag.value == true) { - productList.value = allProductList.where((p0) => p0.nonveg == true || p0.nonveg == false).toList(); + productList.value = + allProductList + .where((p0) => p0.nonveg == true || p0.nonveg == false) + .toList(); } else if (isVag.value == true && isNonVag.value == false) { - productList.value = allProductList.where((p0) => p0.nonveg == false).toList(); + productList.value = + allProductList.where((p0) => p0.nonveg == false).toList(); } else if (isVag.value == false && isNonVag.value == true) { - productList.value = allProductList.where((p0) => p0.nonveg == true).toList(); + productList.value = + allProductList.where((p0) => p0.nonveg == true).toList(); } else if (isVag.value == false && isNonVag.value == false) { - productList.value = allProductList.where((p0) => p0.nonveg == true || p0.nonveg == false).toList(); + productList.value = + allProductList + .where((p0) => p0.nonveg == true || p0.nonveg == false) + .toList(); } } - Future> getProductByCategory(VendorCategoryModel vendorCategoryModel) async { - return productList.where((p0) => p0.categoryID == vendorCategoryModel.id).toList(); + Future> getProductByCategory( + VendorCategoryModel vendorCategoryModel, + ) async { + return productList + .where((p0) => p0.categoryID == vendorCategoryModel.id) + .toList(); } Future getFavouriteList() async { @@ -157,7 +196,9 @@ class RestaurantDetailsController extends GetxController { favouriteItemList.value = value; }); - await FireStoreUtils.getOfferByVendorId(vendorModel.value.id.toString()).then((value) { + await FireStoreUtils.getOfferByVendorId( + vendorModel.value.id.toString(), + ).then((value) { couponList.value = value; }); } @@ -175,8 +216,12 @@ class RestaurantDetailsController extends GetxController { if (day == element.day.toString()) { if (element.timeslot!.isNotEmpty) { for (var element in element.timeslot!) { - var start = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.from}"); - var end = DateFormat("dd-MM-yyyy HH:mm").parse("$date ${element.to}"); + var start = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.from}"); + var end = DateFormat( + "dd-MM-yyyy HH:mm", + ).parse("$date ${element.to}"); if (isCurrentDateInRange(start, end)) { isOpen.value = true; } @@ -219,15 +264,33 @@ class RestaurantDetailsController extends GetxController { String adOnsPrice = "0"; if (productModel.itemAttribute != null) { - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { + if (productModel.itemAttribute!.variants! + .where((element) => element.variantSku == selectedVariants.join('-')) + .isNotEmpty) { variantPrice = Constant.productCommissionPrice( vendorModel.value, - productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0', + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', ); } } else { - String price = Constant.productCommissionPrice(vendorModel.value, productModel.price.toString()); - String disPrice = double.parse(productModel.disPrice.toString()) <= 0 ? "0" : Constant.productCommissionPrice(vendorModel.value, productModel.disPrice.toString()); + String price = Constant.productCommissionPrice( + vendorModel.value, + productModel.price.toString(), + ); + String disPrice = + double.parse(productModel.disPrice.toString()) <= 0 + ? "0" + : Constant.productCommissionPrice( + vendorModel.value, + productModel.disPrice.toString(), + ); if (double.parse(disPrice) <= 0) { variantPrice = price; } else { @@ -237,11 +300,23 @@ class RestaurantDetailsController extends GetxController { for (int i = 0; i < productModel.addOnsPrice!.length; i++) { if (selectedAddOns.contains(productModel.addOnsTitle![i]) == true) { - adOnsPrice = (double.parse(adOnsPrice.toString()) + double.parse(Constant.productCommissionPrice(vendorModel.value, productModel.addOnsPrice![i].toString()))).toString(); + adOnsPrice = + (double.parse(adOnsPrice.toString()) + + double.parse( + Constant.productCommissionPrice( + vendorModel.value, + productModel.addOnsPrice![i].toString(), + ), + )) + .toString(); } } adOnsPrice = (quantity.value * double.parse(adOnsPrice)).toString(); - mainPrice = ((double.parse(variantPrice.toString()) * double.parse(quantity.value.toString())) + double.parse(adOnsPrice.toString())).toString(); + mainPrice = + ((double.parse(variantPrice.toString()) * + double.parse(quantity.value.toString())) + + double.parse(adOnsPrice.toString())) + .toString(); return mainPrice; } @@ -253,18 +328,35 @@ class RestaurantDetailsController extends GetxController { }); } - Future addToCart({required ProductModel productModel, required String price, required String discountPrice, required bool isIncrement, required int quantity, VariantInfo? variantInfo}) async { + Future addToCart({ + required ProductModel productModel, + required String price, + required String discountPrice, + required bool isIncrement, + required int quantity, + VariantInfo? variantInfo, + }) async { CartProductModel cartProductModel = CartProductModel(); String adOnsPrice = "0"; for (int i = 0; i < productModel.addOnsPrice!.length; i++) { - if (selectedAddOns.contains(productModel.addOnsTitle![i]) == true && productModel.addOnsPrice![i] != '0') { - adOnsPrice = (double.parse(adOnsPrice.toString()) + double.parse(Constant.productCommissionPrice(vendorModel.value, productModel.addOnsPrice![i].toString()))).toString(); + if (selectedAddOns.contains(productModel.addOnsTitle![i]) == true && + productModel.addOnsPrice![i] != '0') { + adOnsPrice = + (double.parse(adOnsPrice.toString()) + + double.parse( + Constant.productCommissionPrice( + vendorModel.value, + productModel.addOnsPrice![i].toString(), + ), + )) + .toString(); } } if (variantInfo != null) { - cartProductModel.id = "${productModel.id!}~${variantInfo.variantId.toString()}"; + cartProductModel.id = + "${productModel.id!}~${variantInfo.variantId.toString()}"; cartProductModel.name = productModel.name!; cartProductModel.photo = productModel.photo!; cartProductModel.categoryId = productModel.categoryID!; diff --git a/lib/controllers/restaurant_list_controller.dart b/lib/controllers/restaurant_list_controller.dart index fe953e2..bfe86f8 100644 --- a/lib/controllers/restaurant_list_controller.dart +++ b/lib/controllers/restaurant_list_controller.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/favourite_model.dart'; import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class RestaurantListController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/review_list_controller.dart b/lib/controllers/review_list_controller.dart index 540165c..659bfb5 100644 --- a/lib/controllers/review_list_controller.dart +++ b/lib/controllers/review_list_controller.dart @@ -1,7 +1,7 @@ import 'package:customer/models/rating_model.dart'; import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ReviewListController extends GetxController { RxBool isLoading = true.obs; diff --git a/lib/controllers/scan_qr_code_controller.dart b/lib/controllers/scan_qr_code_controller.dart index 066dcee..8c36a5b 100644 --- a/lib/controllers/scan_qr_code_controller.dart +++ b/lib/controllers/scan_qr_code_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ScanQrCodeController extends GetxController { @override diff --git a/lib/controllers/search_controller.dart b/lib/controllers/search_controller.dart index bf20ea6..01dee30 100644 --- a/lib/controllers/search_controller.dart +++ b/lib/controllers/search_controller.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/product_model.dart'; import 'package:customer/models/vendor_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class SearchScreenController extends GetxController { @override @@ -28,13 +28,20 @@ class SearchScreenController extends GetxController { isLoading.value = false; for (var element in vendorList) { - await FireStoreUtils.getProductByVendorId(element.id.toString()).then((value) { - if ((Constant.isSubscriptionModelApplied == true || element.adminCommission?.isEnabled == true) && element.subscriptionPlan != null) { + await FireStoreUtils.getProductByVendorId(element.id.toString()).then(( + value, + ) { + if ((Constant.isSubscriptionModelApplied == true || + element.adminCommission?.isEnabled == true) && + element.subscriptionPlan != null) { if (element.subscriptionPlan?.itemLimit == '-1') { productList.addAll(value); } else { int selectedProduct = - value.length < int.parse(element.subscriptionPlan?.itemLimit ?? '0') ? (value.isEmpty ? 0 : (value.length)) : int.parse(element.subscriptionPlan?.itemLimit ?? '0'); + value.length < + int.parse(element.subscriptionPlan?.itemLimit ?? '0') + ? (value.isEmpty ? 0 : (value.length)) + : int.parse(element.subscriptionPlan?.itemLimit ?? '0'); productList.addAll(value.sublist(0, selectedProduct)); } } else { diff --git a/lib/controllers/service_list_controller.dart b/lib/controllers/service_list_controller.dart index b12354b..e21ce0f 100644 --- a/lib/controllers/service_list_controller.dart +++ b/lib/controllers/service_list_controller.dart @@ -16,7 +16,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart' as auth; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../screen_ui/auth_screens/login_screen.dart'; import '../screen_ui/multi_vendor_service/dash_board_screens/dash_board_screen.dart'; import '../screen_ui/on_demand_service/on_demand_dashboard_screen.dart'; diff --git a/lib/controllers/sign_up_controller.dart b/lib/controllers/sign_up_controller.dart index 04f9de4..bd990ba 100644 --- a/lib/controllers/sign_up_controller.dart +++ b/lib/controllers/sign_up_controller.dart @@ -3,7 +3,7 @@ import 'package:customer/models/user_model.dart'; import 'package:customer/screen_ui/location_enable_screens/location_permission_screen.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:firebase_auth/firebase_auth.dart' as auth; import '../constant/constant.dart'; import '../models/referral_model.dart'; @@ -17,9 +17,11 @@ class SignUpController extends GetxController { Rx lastNameController = TextEditingController().obs; Rx emailController = TextEditingController().obs; Rx mobileController = TextEditingController().obs; - Rx countryCodeController = TextEditingController(text: Constant.defaultCountryCode).obs; + Rx countryCodeController = + TextEditingController(text: Constant.defaultCountryCode).obs; Rx passwordController = TextEditingController().obs; - Rx confirmPasswordController = TextEditingController().obs; + Rx confirmPasswordController = + TextEditingController().obs; Rx referralController = TextEditingController().obs; final FocusNode emailFocusNode = FocusNode(); @@ -90,7 +92,8 @@ class SignUpController extends GetxController { } else if (lastNameController.value.text.isEmpty) { ShowToastDialog.showToast("Please enter last name".tr()); return false; - } else if (emailController.value.text.isEmpty || !emailController.value.text.isEmail) { + } else if (emailController.value.text.isEmpty || + !emailController.value.text.isEmail) { ShowToastDialog.showToast("Please enter a valid email address".tr()); return false; } else if (mobileController.value.text.isEmpty) { @@ -99,8 +102,11 @@ class SignUpController extends GetxController { } else if (passwordController.value.text.length < 6) { ShowToastDialog.showToast("Password must be at least 6 characters".tr()); return false; - } else if (passwordController.value.text != confirmPasswordController.value.text) { - ShowToastDialog.showToast("Password and Confirm password do not match".tr()); + } else if (passwordController.value.text != + confirmPasswordController.value.text) { + ShowToastDialog.showToast( + "Password and Confirm password do not match".tr(), + ); return false; } return true; @@ -109,7 +115,10 @@ class SignUpController extends GetxController { /// Email Sign-up Flow Future _signUpWithEmail() async { try { - final credential = await _firebaseAuth.createUserWithEmailAndPassword(email: emailController.value.text.trim(), password: passwordController.value.text.trim()); + final credential = await _firebaseAuth.createUserWithEmailAndPassword( + email: emailController.value.text.trim(), + password: passwordController.value.text.trim(), + ); if (credential.user != null) { final newUser = await _buildUserModel(credential.user?.uid ?? ''); @@ -119,7 +128,9 @@ class SignUpController extends GetxController { _navigateBasedOnAddress(newUser); } } on auth.FirebaseAuthException catch (e) { - debugPrint("FirebaseAuthException caught: code=${e.code}, message=${e.message}"); + debugPrint( + "FirebaseAuthException caught: code=${e.code}, message=${e.message}", + ); if (e.code == 'email-already-in-use') { ShowToastDialog.showToast("Email already in use".tr()); } else if (e.code == 'weak-password') { @@ -131,7 +142,9 @@ class SignUpController extends GetxController { } } catch (e) { debugPrint("Something went wrong: ${e.toString()}"); - ShowToastDialog.showToast("${'something_went_wrong'.tr()}: ${e.toString()}"); + ShowToastDialog.showToast( + "${'something_went_wrong'.tr()}: ${e.toString()}", + ); } } @@ -173,9 +186,17 @@ class SignUpController extends GetxController { /// Handle Referral Logic Future _handleReferral(String userId) async { final referralCode = referralController.value.text.trim(); - final referralBy = referralCode.isNotEmpty ? (await FireStoreUtils.getReferralUserByCode(referralCode))?.id ?? '' : ''; + final referralBy = + referralCode.isNotEmpty + ? (await FireStoreUtils.getReferralUserByCode(referralCode))?.id ?? + '' + : ''; - final referral = ReferralModel(id: userId, referralBy: referralBy, referralCode: Constant.getReferralCode()); + final referral = ReferralModel( + id: userId, + referralBy: referralBy, + referralCode: Constant.getReferralCode(), + ); await FireStoreUtils.referralAdd(referral); } @@ -183,7 +204,10 @@ class SignUpController extends GetxController { /// Navigate Based on Shipping Address void _navigateBasedOnAddress(UserModel user) { if (user.shippingAddress?.isNotEmpty == true) { - final defaultAddress = user.shippingAddress!.firstWhere((e) => e.isDefault == true, orElse: () => user.shippingAddress!.first); + final defaultAddress = user.shippingAddress!.firstWhere( + (e) => e.isDefault == true, + orElse: () => user.shippingAddress!.first, + ); /// Save the default address to global constant Constant.selectedLocation = defaultAddress; diff --git a/lib/controllers/splash_controller.dart b/lib/controllers/splash_controller.dart index 3042224..3143267 100644 --- a/lib/controllers/splash_controller.dart +++ b/lib/controllers/splash_controller.dart @@ -7,7 +7,7 @@ import 'package:customer/screen_ui/service_home_screen/service_list_screen.dart' import 'package:customer/utils/notification_service.dart'; import 'package:customer/utils/preferences.dart'; import 'package:firebase_auth/firebase_auth.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../screen_ui/auth_screens/login_screen.dart'; import '../screen_ui/location_enable_screens/location_permission_screen.dart'; import '../screen_ui/on_boarding_screen/on_boarding_screen.dart'; @@ -30,7 +30,9 @@ class SplashController extends GetxController { } else { bool isLogin = await FireStoreUtils.isLogin(); if (isLogin == true) { - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) async { + await FireStoreUtils.getUserProfile( + FireStoreUtils.getCurrentUid(), + ).then((value) async { if (value != null) { UserModel userModel = value; log(userModel.toJson().toString()); @@ -38,11 +40,18 @@ class SplashController extends GetxController { if (userModel.active == true) { userModel.fcmToken = await NotificationService.getToken(); await FireStoreUtils.updateUser(userModel); - if (userModel.shippingAddress != null && userModel.shippingAddress!.isNotEmpty) { - if (userModel.shippingAddress!.where((element) => element.isDefault == true).isNotEmpty) { - Constant.selectedLocation = userModel.shippingAddress!.where((element) => element.isDefault == true).single; + if (userModel.shippingAddress != null && + userModel.shippingAddress!.isNotEmpty) { + if (userModel.shippingAddress! + .where((element) => element.isDefault == true) + .isNotEmpty) { + Constant.selectedLocation = + userModel.shippingAddress! + .where((element) => element.isDefault == true) + .single; } else { - Constant.selectedLocation = userModel.shippingAddress!.first; + Constant.selectedLocation = + userModel.shippingAddress!.first; } Get.offAll(const ServiceListScreen()); } else { diff --git a/lib/controllers/theme_controller.dart b/lib/controllers/theme_controller.dart index 64b05d6..92ebb62 100644 --- a/lib/controllers/theme_controller.dart +++ b/lib/controllers/theme_controller.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../utils/preferences.dart'; class ThemeController extends GetxController { @@ -23,5 +23,3 @@ class ThemeController extends GetxController { ThemeMode get themeMode => isDark.value ? ThemeMode.dark : ThemeMode.light; } - - diff --git a/lib/controllers/view_all_category_controller.dart b/lib/controllers/view_all_category_controller.dart index 1612e88..52ad4a4 100644 --- a/lib/controllers/view_all_category_controller.dart +++ b/lib/controllers/view_all_category_controller.dart @@ -1,7 +1,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/models/vendor_category_model.dart'; import '../service/fire_store_utils.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ViewAllCategoryController extends GetxController { RxBool isLoading = true.obs; @@ -18,12 +18,19 @@ class ViewAllCategoryController extends GetxController { Future getCategoryData() async { await FireStoreUtils.getVendorCategory().then((value) { vendorCategoryModel.value = value; - }); if (Constant.restaurantList != null) { - List usedCategoryIds = Constant.restaurantList!.expand((vendor) => vendor.categoryID ?? []).whereType().toSet().toList(); - vendorCategoryModel.value = vendorCategoryModel.where((category) => usedCategoryIds.contains(category.id)).toList(); + List usedCategoryIds = + Constant.restaurantList! + .expand((vendor) => vendor.categoryID ?? []) + .whereType() + .toSet() + .toList(); + vendorCategoryModel.value = + vendorCategoryModel + .where((category) => usedCategoryIds.contains(category.id)) + .toList(); } isLoading.value = false; diff --git a/lib/controllers/view_all_popular_service_controller.dart b/lib/controllers/view_all_popular_service_controller.dart index 24da089..68379a6 100644 --- a/lib/controllers/view_all_popular_service_controller.dart +++ b/lib/controllers/view_all_popular_service_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/controllers/on_demand_home_controller.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:flutter/material.dart'; import '../models/favorite_ondemand_service_model.dart'; import '../models/provider_serivce_model.dart'; @@ -10,13 +10,17 @@ class ViewAllPopularServiceController extends GetxController { RxList providerList = [].obs; RxList allProviderList = [].obs; RxBool isLoading = true.obs; - Rx onDemandHomeController = Get.find().obs; + Rx onDemandHomeController = + Get.find().obs; - final OnDemandHomeController onDemandController = Get.find(); + final OnDemandHomeController onDemandController = + Get.find(); - Rx searchTextFiledController = TextEditingController().obs; + Rx searchTextFiledController = + TextEditingController().obs; - RxList lstFav = [].obs; + RxList lstFav = + [].obs; @override void onInit() { @@ -29,24 +33,31 @@ class ViewAllPopularServiceController extends GetxController { await FireStoreUtils.getProviderFuture() .then((providerServiceList) { - Set uniqueAuthorIds = providerServiceList.map((service) => service.author).toSet(); + Set uniqueAuthorIds = + providerServiceList.map((service) => service.author).toSet(); List listOfUniqueProviders = uniqueAuthorIds.toList(); List filteredProviders = []; for (var provider in listOfUniqueProviders) { - List filteredList = providerServiceList.where((service) => service.author == provider).toList(); + List filteredList = + providerServiceList + .where((service) => service.author == provider) + .toList(); filteredList.sort((a, b) => a.createdAt!.compareTo(b.createdAt!)); for (int index = 0; index < filteredList.length; index++) { final service = filteredList[index]; - if (Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel?.adminCommision?.isEnabled == true) { + if (Constant.isSubscriptionModelApplied == true || + Constant.sectionConstantModel?.adminCommision?.isEnabled == + true) { if (service.subscriptionPlan?.itemLimit == "-1") { filteredProviders.add(service); } else { - if (index < int.parse(service.subscriptionPlan?.itemLimit ?? '0')) { + if (index < + int.parse(service.subscriptionPlan?.itemLimit ?? '0')) { filteredProviders.add(service); } } @@ -66,7 +77,9 @@ class ViewAllPopularServiceController extends GetxController { }); if (Constant.userModel != null) { - await FireStoreUtils.getFavouritesServiceList(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getFavouritesServiceList( + FireStoreUtils.getCurrentUid(), + ).then((value) { lstFav.value = value; }); } @@ -75,7 +88,14 @@ class ViewAllPopularServiceController extends GetxController { void getFilterData(String value) { if (value.isNotEmpty) { - providerList.value = allProviderList.where((e) => e.title!.toLowerCase().contains(value.toLowerCase()) || e.title!.startsWith(value)).toList(); + providerList.value = + allProviderList + .where( + (e) => + e.title!.toLowerCase().contains(value.toLowerCase()) || + e.title!.startsWith(value), + ) + .toList(); } else { providerList.assignAll(allProviderList); } diff --git a/lib/controllers/view_category_service_controller.dart b/lib/controllers/view_category_service_controller.dart index 58cdaf6..433bd2a 100644 --- a/lib/controllers/view_category_service_controller.dart +++ b/lib/controllers/view_category_service_controller.dart @@ -1,6 +1,6 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/controllers/on_demand_home_controller.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../models/provider_serivce_model.dart'; import '../service/fire_store_utils.dart'; @@ -9,7 +9,8 @@ class ViewCategoryServiceController extends GetxController { RxList providerList = [].obs; RxString categoryId = "".obs, categoryTitle = "".obs; - Rx onDemandHomeController = Get.find().obs; + Rx onDemandHomeController = + Get.find().obs; @override void onInit() { @@ -26,21 +27,32 @@ class ViewCategoryServiceController extends GetxController { providerList.clear(); isLoading.value = true; - List providerServiceList = await FireStoreUtils.getProviderFuture(categoryId: categoryId.value); + List providerServiceList = + await FireStoreUtils.getProviderFuture(categoryId: categoryId.value); - List uniqueAuthId = providerServiceList.map((service) => service.author).toList(); - List uniqueServiceId = providerServiceList.map((service) => service.id).toList(); + List uniqueAuthId = + providerServiceList.map((service) => service.author).toList(); + List uniqueServiceId = + providerServiceList.map((service) => service.id).toList(); List filterByItemLimit = []; List uniqueId = []; - if ((Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel!.adminCommision?.isEnabled == true)) { + if ((Constant.isSubscriptionModelApplied == true || + Constant.sectionConstantModel!.adminCommision?.isEnabled == true)) { for (var authUser in uniqueAuthId) { - List listofAllServiceByAuth = await FireStoreUtils.getAllProviderServiceByAuthorId(authUser!); + List listofAllServiceByAuth = + await FireStoreUtils.getAllProviderServiceByAuthorId(authUser!); for (int i = 0; i < listofAllServiceByAuth.length; i++) { if (listofAllServiceByAuth[i].subscriptionPlan?.itemLimit != null && - (i < int.parse(listofAllServiceByAuth[i].subscriptionPlan?.itemLimit ?? '0') || listofAllServiceByAuth[i].subscriptionPlan?.itemLimit == '-1')) { + (i < + int.parse( + listofAllServiceByAuth[i].subscriptionPlan?.itemLimit ?? + '0', + ) || + listofAllServiceByAuth[i].subscriptionPlan?.itemLimit == + '-1')) { if (uniqueServiceId.contains(listofAllServiceByAuth[i].id)) { filterByItemLimit.add(listofAllServiceByAuth[i]); } @@ -49,7 +61,9 @@ class ViewCategoryServiceController extends GetxController { for (var service in filterByItemLimit) { for (var unique in uniqueServiceId) { - if (service.id == unique && !uniqueId.contains(service.id) && service.subscriptionTotalOrders != '0') { + if (service.id == unique && + !uniqueId.contains(service.id) && + service.subscriptionTotalOrders != '0') { uniqueId.add(service.id); providerList.add(service); } diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 638eddc..44518fb 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -34,7 +34,7 @@ import '../payment/xenditScreen.dart'; import '../service/fire_store_utils.dart'; import 'package:customer/utils/preferences.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:uuid/uuid.dart'; @@ -45,7 +45,8 @@ class WalletController extends GetxController { Rx topUpAmountController = TextEditingController().obs; - RxList walletTransactionList = [].obs; + RxList walletTransactionList = + [].obs; Rx userModel = UserModel().obs; RxString selectedPaymentMethod = "".obs; @@ -71,17 +72,37 @@ class WalletController extends GetxController { Future getPaymentSettings() async { await FireStoreUtils.getPaymentSettingsData().then((value) { - payFastModel.value = PayFastModel.fromJson(jsonDecode(Preferences.getString(Preferences.payFastSettings))); - mercadoPagoModel.value = MercadoPagoModel.fromJson(jsonDecode(Preferences.getString(Preferences.mercadoPago))); - payPalModel.value = PayPalModel.fromJson(jsonDecode(Preferences.getString(Preferences.paypalSettings))); - stripeModel.value = StripeModel.fromJson(jsonDecode(Preferences.getString(Preferences.stripeSettings))); - flutterWaveModel.value = FlutterWaveModel.fromJson(jsonDecode(Preferences.getString(Preferences.flutterWave))); - payStackModel.value = PayStackModel.fromJson(jsonDecode(Preferences.getString(Preferences.payStack))); - razorPayModel.value = RazorPayModel.fromJson(jsonDecode(Preferences.getString(Preferences.razorpaySettings))); + payFastModel.value = PayFastModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payFastSettings)), + ); + mercadoPagoModel.value = MercadoPagoModel.fromJson( + jsonDecode(Preferences.getString(Preferences.mercadoPago)), + ); + payPalModel.value = PayPalModel.fromJson( + jsonDecode(Preferences.getString(Preferences.paypalSettings)), + ); + stripeModel.value = StripeModel.fromJson( + jsonDecode(Preferences.getString(Preferences.stripeSettings)), + ); + flutterWaveModel.value = FlutterWaveModel.fromJson( + jsonDecode(Preferences.getString(Preferences.flutterWave)), + ); + payStackModel.value = PayStackModel.fromJson( + jsonDecode(Preferences.getString(Preferences.payStack)), + ); + razorPayModel.value = RazorPayModel.fromJson( + jsonDecode(Preferences.getString(Preferences.razorpaySettings)), + ); - midTransModel.value = MidTrans.fromJson(jsonDecode(Preferences.getString(Preferences.midTransSettings))); - orangeMoneyModel.value = OrangeMoney.fromJson(json.decode(Preferences.getString(Preferences.orangeMoneySettings))); - xenditModel.value = Xendit.fromJson(jsonDecode(Preferences.getString(Preferences.xenditSettings))); + midTransModel.value = MidTrans.fromJson( + jsonDecode(Preferences.getString(Preferences.midTransSettings)), + ); + orangeMoneyModel.value = OrangeMoney.fromJson( + json.decode(Preferences.getString(Preferences.orangeMoneySettings)), + ); + xenditModel.value = Xendit.fromJson( + jsonDecode(Preferences.getString(Preferences.xenditSettings)), + ); Stripe.publishableKey = stripeModel.value.clientpublishableKey.toString(); Stripe.merchantIdentifier = 'GoRide'; @@ -101,7 +122,9 @@ class WalletController extends GetxController { walletTransactionList.value = value; } }); - await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.getUserProfile(FireStoreUtils.getCurrentUid()).then(( + value, + ) { if (value != null) { userModel.value = value; } @@ -123,9 +146,14 @@ class WalletController extends GetxController { paymentStatus: "success", ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction(transactionModel).then(( + value, + ) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: topUpAmountController.value.text, userId: FireStoreUtils.getCurrentUid()).then((value) { + await FireStoreUtils.updateUserWallet( + amount: topUpAmountController.value.text, + userId: FireStoreUtils.getCurrentUid(), + ).then((value) { getWalletTransaction(); Get.back(); }); @@ -139,20 +167,32 @@ class WalletController extends GetxController { Future stripeMakePayment({required String amount}) async { log(double.parse(amount).toStringAsFixed(0)); try { - Map? paymentIntentData = await createStripeIntent(amount: amount); + Map? paymentIntentData = await createStripeIntent( + amount: amount, + ); log("stripe Responce====>$paymentIntentData"); if (paymentIntentData!.containsKey("error")) { Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } else { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: paymentIntentData['client_secret'], allowsDelayedPaymentMethods: false, - googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US', testEnv: true, currencyCode: "USD"), + googlePay: const PaymentSheetGooglePay( + merchantCountryCode: 'US', + testEnv: true, + currencyCode: "USD", + ), customFlow: true, style: ThemeMode.system, - appearance: PaymentSheetAppearance(colors: PaymentSheetAppearanceColors(primary: AppThemeData.primary300)), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + primary: AppThemeData.primary300, + ), + ), merchantDisplayName: 'GoRide', ), ); @@ -198,7 +238,10 @@ class WalletController extends GetxController { var response = await http.post( Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, - headers: {'Authorization': 'Bearer $stripeSecret', 'Content-Type': 'application/x-www-form-urlencoded'}, + headers: { + 'Authorization': 'Bearer $stripeSecret', + 'Content-Type': 'application/x-www-form-urlencoded', + }, ); return jsonDecode(response.body); @@ -208,8 +251,14 @@ class WalletController extends GetxController { } //mercadoo - Future mercadoPagoMakePayment({required BuildContext context, required String amount}) async { - final headers = {'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', 'Content-Type': 'application/json'}; + Future mercadoPagoMakePayment({ + required BuildContext context, + required String amount, + }) async { + final headers = { + 'Authorization': 'Bearer ${mercadoPagoModel.value.accessToken}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "items": [ @@ -222,11 +271,20 @@ class WalletController extends GetxController { }, ], "payer": {"email": userModel.value.email}, - "back_urls": {"failure": "${Constant.globalUrl}payment/failure", "pending": "${Constant.globalUrl}payment/pending", "success": "${Constant.globalUrl}payment/success"}, - "auto_return": "approved", // Automatically return after payment is approved + "back_urls": { + "failure": "${Constant.globalUrl}payment/failure", + "pending": "${Constant.globalUrl}payment/pending", + "success": "${Constant.globalUrl}payment/success", + }, + "auto_return": + "approved", // Automatically return after payment is approved }); - final response = await http.post(Uri.parse("https://api.mercadopago.com/checkout/preferences"), headers: headers, body: body); + final response = await http.post( + Uri.parse("https://api.mercadopago.com/checkout/preferences"), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); @@ -239,7 +297,9 @@ class WalletController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something want wrong please contact administrator".tr()); + ShowToastDialog.showToast( + "Something want wrong please contact administrator".tr(), + ); print('Error creating preference: ${response.body}'); return null; } @@ -284,9 +344,12 @@ class WalletController extends GetxController { ///PayStack Payment Method Future payStackPayment(String totalAmount) async { - await PayStackURLGen.payStackURLGen(amount: (double.parse(totalAmount) * 100).toString(), currency: "ZAR", secretKey: payStackModel.value.secretKey.toString(), userModel: userModel.value).then(( - value, - ) async { + await PayStackURLGen.payStackURLGen( + amount: (double.parse(totalAmount) * 100).toString(), + currency: "ZAR", + secretKey: payStackModel.value.secretKey.toString(), + userModel: userModel.value, + ).then((value) async { if (value != null) { PayStackUrlModel payStackModel0 = value; Get.to( @@ -306,15 +369,23 @@ class WalletController extends GetxController { } }); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); } }); } //flutter wave Payment Method - Future flutterWaveInitiatePayment({required BuildContext context, required String amount}) async { + Future flutterWaveInitiatePayment({ + required BuildContext context, + required String amount, + }) async { final url = Uri.parse('https://api.flutterwave.com/v3/payments'); - final headers = {'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', 'Content-Type': 'application/json'}; + final headers = { + 'Authorization': 'Bearer ${flutterWaveModel.value.secretKey}', + 'Content-Type': 'application/json', + }; final body = jsonEncode({ "tx_ref": _ref, @@ -327,14 +398,19 @@ class WalletController extends GetxController { "phonenumber": userModel.value.phoneNumber, // Add a real phone number "name": userModel.value.fullName(), // Add a real customer name }, - "customizations": {"title": "Payment for Services", "description": "Payment for XYZ services"}, + "customizations": { + "title": "Payment for Services", + "description": "Payment for XYZ services", + }, }); final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body); - Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then((value) { + Get.to(MercadoPagoScreen(initialURl: data['data']['link']))!.then(( + value, + ) { if (value) { ShowToastDialog.showToast("Payment Successful!!".tr()); walletTopUp(); @@ -363,8 +439,14 @@ class WalletController extends GetxController { // payFast void payFastPayment({required BuildContext context, required String amount}) { - PayStackURLGen.getPayHTML(payFastSettingData: payFastModel.value, amount: amount.toString(), userModel: userModel.value).then((String? value) async { - bool isDone = await Get.to(PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value)); + PayStackURLGen.getPayHTML( + payFastSettingData: payFastModel.value, + amount: amount.toString(), + userModel: userModel.value, + ).then((String? value) async { + bool isDone = await Get.to( + PayFastScreen(htmlData: value!, payFastSettingData: payFastModel.value), + ); if (isDone) { Get.back(); ShowToastDialog.showToast("Payment successfully".tr()); @@ -389,7 +471,10 @@ class WalletController extends GetxController { 'description': 'wallet Topup', 'retry': {'enabled': true, 'max_count': 1}, 'send_sms_hash': true, - 'prefill': {'contact': userModel.value.phoneNumber, 'email': userModel.value.email}, + 'prefill': { + 'contact': userModel.value.phoneNumber, + 'email': userModel.value.email, + }, 'external': { 'wallets': ['paytm'], }, @@ -418,7 +503,10 @@ class WalletController extends GetxController { } //Midtrans payment - Future midtransMakePayment({required String amount, required BuildContext context}) async { + Future midtransMakePayment({ + required String amount, + required BuildContext context, + }) async { await createPaymentLink(amount: amount).then((url) { ShowToastDialog.closeLoader(); if (url != '') { @@ -436,15 +524,30 @@ class WalletController extends GetxController { Future createPaymentLink({required var amount}) async { var ordersId = const Uuid().v1(); - final url = Uri.parse(midTransModel.value.isSandbox! ? 'https://api.sandbox.midtrans.com/v1/payment-links' : 'https://api.midtrans.com/v1/payment-links'); + final url = Uri.parse( + midTransModel.value.isSandbox! + ? 'https://api.sandbox.midtrans.com/v1/payment-links' + : 'https://api.midtrans.com/v1/payment-links', + ); final response = await http.post( url, - headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(midTransModel.value.serverKey!)}, + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader( + midTransModel.value.serverKey!, + ), + }, body: jsonEncode({ - 'transaction_details': {'order_id': ordersId, 'gross_amount': double.parse(amount.toString()).toInt()}, + 'transaction_details': { + 'order_id': ordersId, + 'gross_amount': double.parse(amount.toString()).toInt(), + }, 'usage_limit': 2, - "callbacks": {"finish": "https://www.google.com?merchant_order_id=$ordersId"}, + "callbacks": { + "finish": "https://www.google.com?merchant_order_id=$ordersId", + }, }), ); @@ -452,7 +555,9 @@ class WalletController extends GetxController { final responseData = jsonDecode(response.body); return responseData['payment_url']; } else { - ShowToastDialog.showToast("something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -469,13 +574,30 @@ class WalletController extends GetxController { static String orderId = ''; static String amount = ''; - Future orangeMakePayment({required String amount, required BuildContext context}) async { + Future orangeMakePayment({ + required String amount, + required BuildContext context, + }) async { reset(); var id = const Uuid().v4(); - var paymentURL = await fetchToken(context: context, orderId: id, amount: amount, currency: 'USD'); + var paymentURL = await fetchToken( + context: context, + orderId: id, + amount: amount, + currency: 'USD', + ); ShowToastDialog.closeLoader(); if (paymentURL.toString() != '') { - Get.to(() => OrangeMoneyScreen(initialURl: paymentURL, accessToken: accessToken, amount: amount, orangePay: orangeMoneyModel.value, orderId: orderId, payToken: payToken))!.then((value) { + Get.to( + () => OrangeMoneyScreen( + initialURl: paymentURL, + accessToken: accessToken, + amount: amount, + orangePay: orangeMoneyModel.value, + orderId: orderId, + payToken: payToken, + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); walletTopUp(); @@ -486,13 +608,22 @@ class WalletController extends GetxController { } } - Future fetchToken({required String orderId, required String currency, required BuildContext context, required String amount}) async { + Future fetchToken({ + required String orderId, + required String currency, + required BuildContext context, + required String amount, + }) async { String apiUrl = 'https://api.orange.com/oauth/v3/token'; Map requestBody = {'grant_type': 'client_credentials'}; var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': "Basic ${orangeMoneyModel.value.auth!}", 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}, + headers: { + 'Authorization': "Basic ${orangeMoneyModel.value.auth!}", + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, body: requestBody, ); @@ -500,17 +631,32 @@ class WalletController extends GetxController { Map responseData = jsonDecode(response.body); accessToken = responseData['access_token']; - return await webpayment(context: context, amountData: amount, currency: currency, orderIdData: orderId); + return await webpayment( + context: context, + amountData: amount, + currency: currency, + orderIdData: orderId, + ); } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } - Future webpayment({required String orderIdData, required BuildContext context, required String currency, required String amountData}) async { + Future webpayment({ + required String orderIdData, + required BuildContext context, + required String currency, + required String amountData, + }) async { orderId = orderIdData; amount = amountData; - String apiUrl = orangeMoneyModel.value.isSandbox! == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; + String apiUrl = + orangeMoneyModel.value.isSandbox! == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/webpayment' + : 'https://api.orange.com/orange-money-webpay/cm/v1/webpayment'; Map requestBody = { "merchant_key": orangeMoneyModel.value.merchantKey ?? '', "currency": orangeMoneyModel.value.isSandbox == true ? "OUV" : currency, @@ -525,7 +671,11 @@ class WalletController extends GetxController { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); print(response.statusCode); @@ -541,7 +691,9 @@ class WalletController extends GetxController { return ''; } } else { - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); + ShowToastDialog.showToast( + "Something went wrong, please contact admin.".tr(), + ); return ''; } } @@ -558,7 +710,13 @@ class WalletController extends GetxController { await createXenditInvoice(amount: amount).then((model) { ShowToastDialog.closeLoader(); if (model.id != null) { - Get.to(() => XenditScreen(initialURl: model.invoiceUrl ?? '', transId: model.id ?? '', apiKey: xenditModel.value.apiKey!.toString()))!.then((value) { + Get.to( + () => XenditScreen( + initialURl: model.invoiceUrl ?? '', + transId: model.id ?? '', + apiKey: xenditModel.value.apiKey!.toString(), + ), + )!.then((value) { if (value == true) { ShowToastDialog.showToast("Payment Successful!!".tr()); walletTopUp(); @@ -574,7 +732,9 @@ class WalletController extends GetxController { const url = 'https://api.xendit.co/v2/invoices'; var headers = { 'Content-Type': 'application/json', - 'Authorization': generateBasicAuthHeader(xenditModel.value.apiKey!.toString()), + 'Authorization': generateBasicAuthHeader( + xenditModel.value.apiKey!.toString(), + ), // 'Cookie': '__cf_bm=yERkrx3xDITyFGiou0bbKY1bi7xEwovHNwxV1vCNbVc-1724155511-1.0.1.1-jekyYQmPCwY6vIJ524K0V6_CEw6O.dAwOmQnHtwmaXO_MfTrdnmZMka0KZvjukQgXu5B.K_6FJm47SGOPeWviQ', }; @@ -587,7 +747,11 @@ class WalletController extends GetxController { }); try { - final response = await http.post(Uri.parse(url), headers: headers, body: body); + final response = await http.post( + Uri.parse(url), + headers: headers, + body: body, + ); if (response.statusCode == 200 || response.statusCode == 201) { XenditModel model = XenditModel.fromJson(jsonDecode(response.body)); diff --git a/lib/main.dart b/lib/main.dart index bc48340..94ab4a6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,6 +13,8 @@ import 'controllers/global_setting_controller.dart'; import 'controllers/theme_controller.dart'; import 'firebase_options.dart'; + + void main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); diff --git a/lib/payment/MercadoPagoScreen.dart b/lib/payment/MercadoPagoScreen.dart index f296a79..432e62c 100644 --- a/lib/payment/MercadoPagoScreen.dart +++ b/lib/payment/MercadoPagoScreen.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:customer/constant/constant.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:webview_flutter/webview_flutter.dart'; class MercadoPagoScreen extends StatefulWidget { @@ -36,10 +36,17 @@ class _MercadoPagoScreenState extends State { onWebResourceError: (WebResourceError error) {}, onNavigationRequest: (NavigationRequest navigation) async { debugPrint("--->2 ${navigation.url}"); - if (navigation.url.contains("${Constant.globalUrl}payment/success")) { + if (navigation.url.contains( + "${Constant.globalUrl}payment/success", + )) { Get.back(result: true); } - if (navigation.url.contains("${Constant.globalUrl}payment/failure") || navigation.url.contains("${Constant.globalUrl}payment/pending")) { + if (navigation.url.contains( + "${Constant.globalUrl}payment/failure", + ) || + navigation.url.contains( + "${Constant.globalUrl}payment/pending", + )) { Get.back(result: false); } return NavigationDecision.navigate; @@ -82,14 +89,20 @@ class _MercadoPagoScreenState extends State { content: SingleChildScrollView(child: Text("Cancel Payment?".tr())), actions: [ TextButton( - child: Text('Cancel'.tr(), style: const TextStyle(color: Colors.red)), + child: Text( + 'Cancel'.tr(), + style: const TextStyle(color: Colors.red), + ), onPressed: () { Navigator.of(context).pop(); Get.back(result: false); }, ), TextButton( - child: Text('Continue'.tr(), style: const TextStyle(color: Colors.green)), + child: Text( + 'Continue'.tr(), + style: const TextStyle(color: Colors.green), + ), onPressed: () { Navigator.of(context).pop(); }, diff --git a/lib/payment/PayFastScreen.dart b/lib/payment/PayFastScreen.dart index 5b24b4e..d1cd451 100644 --- a/lib/payment/PayFastScreen.dart +++ b/lib/payment/PayFastScreen.dart @@ -6,14 +6,18 @@ import 'package:customer/models/payment_model/pay_fast_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:webview_flutter/webview_flutter.dart'; class PayFastScreen extends StatefulWidget { final String htmlData; final PayFastModel payFastSettingData; - const PayFastScreen({super.key, required this.htmlData, required this.payFastSettingData}); + const PayFastScreen({ + super.key, + required this.htmlData, + required this.payFastSettingData, + }); @override State createState() => _PayFastScreenState(); @@ -45,9 +49,11 @@ class _PayFastScreenState extends State { } if (navigation.url == widget.payFastSettingData.returnUrl) { Get.back(result: true); - } else if (navigation.url == widget.payFastSettingData.notifyUrl) { + } else if (navigation.url == + widget.payFastSettingData.notifyUrl) { Get.back(result: false); - } else if (navigation.url == widget.payFastSettingData.cancelUrl) { + } else if (navigation.url == + widget.payFastSettingData.cancelUrl) { _showMyDialog(); } return NavigationDecision.navigate; @@ -95,7 +101,10 @@ class _PayFastScreenState extends State { }, ), TextButton( - child: Text('Continue Payment'.tr(), style: TextStyle(color: Colors.green)), + child: Text( + 'Continue Payment'.tr(), + style: TextStyle(color: Colors.green), + ), onPressed: () { Get.back(); }, diff --git a/lib/payment/midtrans_screen.dart b/lib/payment/midtrans_screen.dart index 7336b51..9c6c6c2 100644 --- a/lib/payment/midtrans_screen.dart +++ b/lib/payment/midtrans_screen.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:webview_flutter/webview_flutter.dart'; class MidtransScreen extends StatefulWidget { @@ -48,7 +48,10 @@ class _MidtransScreenState extends State { Get.back(result: false); } } else { - String? orderId = Uri.parse(navigation.url).queryParameters['merchant_order_id']; + String? orderId = + Uri.parse( + navigation.url, + ).queryParameters['merchant_order_id']; if (orderId != null) { Get.back(result: true); } else { @@ -81,7 +84,16 @@ class _MidtransScreenState extends State { child: const Icon(Icons.arrow_back, color: Colors.white), ), ), - body: Stack(alignment: Alignment.center, children: [WebViewWidget(controller: controller), Visibility(visible: isLoading, child: const Center(child: CircularProgressIndicator()))]), + body: Stack( + alignment: Alignment.center, + children: [ + WebViewWidget(controller: controller), + Visibility( + visible: isLoading, + child: const Center(child: CircularProgressIndicator()), + ), + ], + ), ), ); } @@ -96,14 +108,20 @@ class _MidtransScreenState extends State { content: SingleChildScrollView(child: Text("Cancel Payment?".tr())), actions: [ TextButton( - child: Text('Cancel'.tr(), style: const TextStyle(color: Colors.red)), + child: Text( + 'Cancel'.tr(), + style: const TextStyle(color: Colors.red), + ), onPressed: () { Get.back(result: false); Get.back(result: false); }, ), TextButton( - child: Text('Continue'.tr(), style: const TextStyle(color: Colors.green)), + child: Text( + 'Continue'.tr(), + style: const TextStyle(color: Colors.green), + ), onPressed: () { Get.back(result: false); }, diff --git a/lib/payment/orangePayScreen.dart b/lib/payment/orangePayScreen.dart index 47e0f6b..7d2bbd7 100644 --- a/lib/payment/orangePayScreen.dart +++ b/lib/payment/orangePayScreen.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'package:customer/models/payment_model/orange_money.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:webview_flutter/webview_flutter.dart'; @@ -17,7 +17,15 @@ class OrangeMoneyScreen extends StatefulWidget { String orderId = ''; String amount = ''; - OrangeMoneyScreen({super.key, required this.initialURl, required this.orangePay, required this.accessToken, required this.payToken, required this.orderId, required this.amount}); + OrangeMoneyScreen({ + super.key, + required this.initialURl, + required this.orangePay, + required this.accessToken, + required this.payToken, + required this.orderId, + required this.amount, + }); @override State createState() => _OrangeMoneyScreenState(); @@ -41,7 +49,12 @@ class _OrangeMoneyScreenState extends State { timer = Timer.periodic(const Duration(seconds: 3), (Timer t) async { if (!mounted) return; - String status = await transactionStatus(accessToken: widget.accessToken, amount: widget.amount, orderId: widget.orderId, payToken: widget.payToken); + String status = await transactionStatus( + accessToken: widget.accessToken, + amount: widget.amount, + orderId: widget.orderId, + payToken: widget.payToken, + ); if (status == 'SUCCESS') { timer?.cancel(); @@ -72,15 +85,31 @@ class _OrangeMoneyScreenState extends State { ..loadRequest(Uri.parse(widget.initialURl)); } - Future transactionStatus({required String orderId, required String amount, required String payToken, required String accessToken}) async { - String apiUrl = widget.orangePay.isSandbox == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/transactionstatus' : 'https://api.orange.com/orange-money-webpay/cm/v1/transactionstatus'; + Future transactionStatus({ + required String orderId, + required String amount, + required String payToken, + required String accessToken, + }) async { + String apiUrl = + widget.orangePay.isSandbox == true + ? 'https://api.orange.com/orange-money-webpay/dev/v1/transactionstatus' + : 'https://api.orange.com/orange-money-webpay/cm/v1/transactionstatus'; - Map requestBody = {"order_id": orderId, "amount": amount, "pay_token": payToken}; + Map requestBody = { + "order_id": orderId, + "amount": amount, + "pay_token": payToken, + }; try { var response = await http.post( Uri.parse(apiUrl), - headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: { + 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, body: json.encode(requestBody), ); @@ -107,10 +136,16 @@ class _OrangeMoneyScreenState extends State { child: Scaffold( appBar: AppBar( backgroundColor: Colors.black, - leading: IconButton(icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: _showCancelDialog), + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + onPressed: _showCancelDialog, + ), title: Text('Orange Money Payment'.tr()), ), - body: isLoading ? const Center(child: CircularProgressIndicator()) : WebViewWidget(controller: controller), + body: + isLoading + ? const Center(child: CircularProgressIndicator()) + : WebViewWidget(controller: controller), ), ); } @@ -124,9 +159,12 @@ class _OrangeMoneyScreenState extends State { title: Text('Cancel Payment'.tr()), content: Text('Are you sure you want to cancel this payment?'.tr()), actions: [ - TextButton(child: Text('No', style: TextStyle(color: Colors.green)), onPressed: () => Get.back()), TextButton( - child: Text('Yes'.tr(), style: TextStyle(color: Colors.red)), + child: Text('No', style: TextStyle(color: Colors.green)), + onPressed: () => Get.back(), + ), + TextButton( + child: Text('Yes'.tr(), style: TextStyle(color: Colors.red)), onPressed: () { timer?.cancel(); Get.back(); // close dialog @@ -152,8 +190,7 @@ class _OrangeMoneyScreenState extends State { // import 'dart:convert'; // import 'package:customer/models/payment_model/orange_money.dart'; // import 'package:flutter/material.dart'; -// import 'package:get/get.dart'; -// import 'package:http/http.dart' as http; +// import 'package:get/get.dart' hide Trans;// import 'package:http/http.dart' as http; // import 'package:webview_flutter/webview_flutter.dart'; // // class OrangeMoneyScreen extends StatefulWidget { diff --git a/lib/payment/paystack/pay_stack_screen.dart b/lib/payment/paystack/pay_stack_screen.dart index d33d2b4..51d3854 100644 --- a/lib/payment/paystack/pay_stack_screen.dart +++ b/lib/payment/paystack/pay_stack_screen.dart @@ -4,7 +4,7 @@ import 'package:customer/payment/paystack/paystack_url_genrater.dart'; import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:webview_flutter/webview_flutter.dart'; class PayStackScreen extends StatefulWidget { @@ -14,7 +14,14 @@ class PayStackScreen extends StatefulWidget { final String secretKey; final String callBackUrl; - const PayStackScreen({super.key, required this.initialURl, required this.reference, required this.amount, required this.secretKey, required this.callBackUrl}); + const PayStackScreen({ + super.key, + required this.initialURl, + required this.reference, + required this.amount, + required this.secretKey, + required this.callBackUrl, + }); @override State createState() => _PayStackScreenState(); @@ -30,37 +37,52 @@ class _PayStackScreenState extends State { } void initController() { - controller = WebViewController() - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setBackgroundColor(const Color(0x00000000)) - ..setNavigationDelegate( - NavigationDelegate( - onProgress: (int progress) { - // Update loading bar. - }, - onPageStarted: (String url) {}, - onPageFinished: (String url) {}, - onWebResourceError: (WebResourceError error) {}, - onNavigationRequest: (NavigationRequest navigation) async { - debugPrint("--->2${navigation.url}"); - debugPrint("--->2" "${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}"); - if (navigation.url == 'https://foodieweb.siswebapp.com/success?trxref=${widget.reference}&reference=${widget.reference}' || - navigation.url == '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') { - final isDone = await PayStackURLGen.verifyTransaction(secretKey: widget.secretKey, reference: widget.reference, amount: widget.amount); - Get.back(result: isDone); - } - if ((navigation.url == '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') || - (navigation.url == "https://hello.pstk.xyz/callback") || - (navigation.url == 'https://standard.paystack.co/close') || - (navigation.url == 'https://talazo.app/login')) { - final isDone = await PayStackURLGen.verifyTransaction(secretKey: widget.secretKey, reference: widget.reference, amount: widget.amount); - Get.back(result: isDone); - } - return NavigationDecision.navigate; - }, - ), - ) - ..loadRequest(Uri.parse(widget.initialURl)); + controller = + WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(const Color(0x00000000)) + ..setNavigationDelegate( + NavigationDelegate( + onProgress: (int progress) { + // Update loading bar. + }, + onPageStarted: (String url) {}, + onPageFinished: (String url) {}, + onWebResourceError: (WebResourceError error) {}, + onNavigationRequest: (NavigationRequest navigation) async { + debugPrint("--->2${navigation.url}"); + debugPrint( + "--->2" + "${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}", + ); + if (navigation.url == + 'https://foodieweb.siswebapp.com/success?trxref=${widget.reference}&reference=${widget.reference}' || + navigation.url == + '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') { + final isDone = await PayStackURLGen.verifyTransaction( + secretKey: widget.secretKey, + reference: widget.reference, + amount: widget.amount, + ); + Get.back(result: isDone); + } + if ((navigation.url == + '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') || + (navigation.url == "https://hello.pstk.xyz/callback") || + (navigation.url == 'https://standard.paystack.co/close') || + (navigation.url == 'https://talazo.app/login')) { + final isDone = await PayStackURLGen.verifyTransaction( + secretKey: widget.secretKey, + reference: widget.reference, + amount: widget.amount, + ); + Get.back(result: isDone); + } + return NavigationDecision.navigate; + }, + ), + ) + ..loadRequest(Uri.parse(widget.initialURl)); } @override @@ -72,17 +94,16 @@ class _PayStackScreenState extends State { }, child: Scaffold( appBar: AppBar( - backgroundColor: AppThemeData.grey50, - title: Text("Payment".tr()), - centerTitle: false, - leading: GestureDetector( - onTap: () { - _showMyDialog(); - }, - child: const Icon( - Icons.arrow_back, - ), - )), + backgroundColor: AppThemeData.grey50, + title: Text("Payment".tr()), + centerTitle: false, + leading: GestureDetector( + onTap: () { + _showMyDialog(); + }, + child: const Icon(Icons.arrow_back), + ), + ), body: WebViewWidget(controller: controller), ), ); @@ -95,15 +116,10 @@ class _PayStackScreenState extends State { builder: (BuildContext context) { return AlertDialog( title: const Text('Cancel Payment'), - content: const SingleChildScrollView( - child: Text("cancelPayment?"), - ), + content: const SingleChildScrollView(child: Text("cancelPayment?")), actions: [ TextButton( - child: const Text( - 'Cancel', - style: TextStyle(color: Colors.red), - ), + child: const Text('Cancel', style: TextStyle(color: Colors.red)), onPressed: () { Navigator.of(context).pop(); Navigator.of(context).pop(false); diff --git a/lib/payment/xenditScreen.dart b/lib/payment/xenditScreen.dart index b3ace2b..0f3b178 100644 --- a/lib/payment/xenditScreen.dart +++ b/lib/payment/xenditScreen.dart @@ -5,7 +5,7 @@ import 'dart:developer'; import 'package:customer/payment/xenditModel.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import 'package:webview_flutter/webview_flutter.dart'; @@ -14,7 +14,12 @@ class XenditScreen extends StatefulWidget { final String transId; final String apiKey; - const XenditScreen({super.key, required this.initialURl, required this.transId, required this.apiKey}); + const XenditScreen({ + super.key, + required this.initialURl, + required this.transId, + required this.apiKey, + }); @override State createState() => _XenditScreenState(); @@ -102,7 +107,16 @@ class _XenditScreenState extends State { child: const Icon(Icons.arrow_back, color: Colors.white), ), ), - body: Stack(alignment: Alignment.center, children: [WebViewWidget(controller: controller), Visibility(visible: isLoading, child: const Center(child: CircularProgressIndicator()))]), + body: Stack( + alignment: Alignment.center, + children: [ + WebViewWidget(controller: controller), + Visibility( + visible: isLoading, + child: const Center(child: CircularProgressIndicator()), + ), + ], + ), ), ); } @@ -117,14 +131,20 @@ class _XenditScreenState extends State { content: SingleChildScrollView(child: Text("Cancel Payment?".tr())), actions: [ TextButton( - child: Text('Cancel'.tr(), style: const TextStyle(color: Colors.red)), + child: Text( + 'Cancel'.tr(), + style: const TextStyle(color: Colors.red), + ), onPressed: () { Navigator.of(context).pop(false); Navigator.of(context).pop(false); }, ), TextButton( - child: Text('Continue'.tr(), style: const TextStyle(color: Colors.green)), + child: Text( + 'Continue'.tr(), + style: const TextStyle(color: Colors.green), + ), onPressed: () { Navigator.of(context).pop(false); }, @@ -140,7 +160,10 @@ class _XenditScreenState extends State { var url = Uri.parse('https://api.xendit.co/v2/invoices/$paymentId'); // Headers - var headers = {'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(widget.apiKey.toString())}; + var headers = { + 'Content-Type': 'application/json', + 'Authorization': generateBasicAuthHeader(widget.apiKey.toString()), + }; // Making the POST request var response = await http.get(url, headers: headers); diff --git a/lib/screen_ui/auth_screens/forgot_password_screen.dart b/lib/screen_ui/auth_screens/forgot_password_screen.dart index 894fed1..e1ab3ad 100644 --- a/lib/screen_ui/auth_screens/forgot_password_screen.dart +++ b/lib/screen_ui/auth_screens/forgot_password_screen.dart @@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/forgot_password_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; diff --git a/lib/screen_ui/auth_screens/login_screen.dart b/lib/screen_ui/auth_screens/login_screen.dart index 24e3116..620ffc7 100644 --- a/lib/screen_ui/auth_screens/login_screen.dart +++ b/lib/screen_ui/auth_screens/login_screen.dart @@ -13,7 +13,7 @@ import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; import '../../themes/round_button_fill.dart'; import '../../themes/text_field_widget.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'forgot_password_screen.dart'; import 'mobile_login_screen.dart'; @@ -72,8 +72,7 @@ class LoginScreen extends StatelessWidget { children: [ const SizedBox(height: 20), Text( - ConstTexts.loginToExplore.tr() - , + ConstTexts.loginToExplore.tr(), style: AppThemeData.boldTextStyle( fontSize: 24, color: @@ -143,7 +142,7 @@ class LoginScreen extends StatelessWidget { ), const SizedBox(height: 20), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.login.tr(), onPress: controller.loginWithEmail, color: @@ -218,7 +217,7 @@ class LoginScreen extends StatelessWidget { children: [ Expanded( child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.withGoogle.tr(), textColor: isDark @@ -242,7 +241,7 @@ class LoginScreen extends StatelessWidget { Platform.isIOS ? Expanded( child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.withApple.tr(), isCenter: true, textColor: diff --git a/lib/screen_ui/auth_screens/mobile_login_screen.dart b/lib/screen_ui/auth_screens/mobile_login_screen.dart index 9d1164c..7a04934 100644 --- a/lib/screen_ui/auth_screens/mobile_login_screen.dart +++ b/lib/screen_ui/auth_screens/mobile_login_screen.dart @@ -7,7 +7,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/assets.dart'; import '../../constant/constant.dart'; import '../../controllers/mobile_login_controller.dart'; diff --git a/lib/screen_ui/auth_screens/otp_verification_screen.dart b/lib/screen_ui/auth_screens/otp_verification_screen.dart index 7a62a97..251e952 100644 --- a/lib/screen_ui/auth_screens/otp_verification_screen.dart +++ b/lib/screen_ui/auth_screens/otp_verification_screen.dart @@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:pin_code_fields/pin_code_fields.dart'; import '../../constant/assets.dart'; import '../../controllers/otp_verification_controller.dart'; diff --git a/lib/screen_ui/auth_screens/sign_up_screen.dart b/lib/screen_ui/auth_screens/sign_up_screen.dart index 51fc91c..9ea4b1f 100644 --- a/lib/screen_ui/auth_screens/sign_up_screen.dart +++ b/lib/screen_ui/auth_screens/sign_up_screen.dart @@ -13,7 +13,7 @@ import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; import '../../themes/round_button_fill.dart'; import '../../themes/text_field_widget.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'login_screen.dart'; import 'mobile_login_screen.dart'; diff --git a/lib/screen_ui/cab_service_screens/Intercity_home_screen.dart b/lib/screen_ui/cab_service_screens/Intercity_home_screen.dart index 45d7169..33fcf94 100644 --- a/lib/screen_ui/cab_service_screens/Intercity_home_screen.dart +++ b/lib/screen_ui/cab_service_screens/Intercity_home_screen.dart @@ -19,7 +19,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:geocoding/geocoding.dart' as get_cord_address; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter_map/flutter_map.dart' as flutterMap; import 'package:latlong2/latlong.dart' as latlong; @@ -59,19 +59,57 @@ class IntercityHomeScreen extends StatelessWidget { options: flutterMap.MapOptions( initialCenter: Constant.currentLocation != null - ? latlong.LatLng(Constant.currentLocation!.latitude, Constant.currentLocation!.longitude) + ? latlong.LatLng( + Constant.currentLocation!.latitude, + Constant.currentLocation!.longitude, + ) : controller.currentOrder.value.id != null ? latlong.LatLng( - double.parse(controller.currentOrder.value.sourceLocation!.latitude.toString()), - double.parse(controller.currentOrder.value.sourceLocation!.longitude.toString()), + double.parse( + controller + .currentOrder + .value + .sourceLocation! + .latitude + .toString(), + ), + double.parse( + controller + .currentOrder + .value + .sourceLocation! + .longitude + .toString(), + ), ) - : latlong.LatLng(41.4219057, -102.0840772), + : latlong.LatLng( + 41.4219057, + -102.0840772, + ), initialZoom: 14, ), children: [ - flutterMap.TileLayer(urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: Platform.isAndroid ? "com.emart" : "com.emart.ios"), - flutterMap.MarkerLayer(markers: controller.osmMarker), - if (controller.routePoints.isNotEmpty) flutterMap.PolylineLayer(polylines: [flutterMap.Polyline(points: controller.routePoints, strokeWidth: 5.0, color: Colors.blue)]), + flutterMap.TileLayer( + urlTemplate: + 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: + Platform.isAndroid + ? "com.emart" + : "com.emart.ios", + ), + flutterMap.MarkerLayer( + markers: controller.osmMarker, + ), + if (controller.routePoints.isNotEmpty) + flutterMap.PolylineLayer( + polylines: [ + flutterMap.Polyline( + points: controller.routePoints, + strokeWidth: 5.0, + color: Colors.blue, + ), + ], + ), ], ) : GoogleMap( @@ -79,16 +117,26 @@ class IntercityHomeScreen extends StatelessWidget { controller.mapController = googleMapController; if (Constant.currentLocation != null) { - controller.setDepartureMarker(Constant.currentLocation!.latitude, Constant.currentLocation!.longitude); + controller.setDepartureMarker( + Constant.currentLocation!.latitude, + Constant.currentLocation!.longitude, + ); controller.searchPlaceNameGoogle(); } }, - initialCameraPosition: CameraPosition(target: controller.currentPosition.value, zoom: 14), + initialCameraPosition: CameraPosition( + target: controller.currentPosition.value, + zoom: 14, + ), myLocationEnabled: true, zoomControlsEnabled: true, zoomGesturesEnabled: true, - polylines: Set.of(controller.polyLines.values), - markers: controller.markers.toSet(), // reactive marker set + polylines: Set.of( + controller.polyLines.values, + ), + markers: + controller.markers + .toSet(), // reactive marker set ), Positioned( top: 50, @@ -96,36 +144,64 @@ class IntercityHomeScreen extends StatelessWidget { right: Constant.isRtl ? 20 : null, child: InkWell( onTap: () { - if (controller.bottomSheetType.value == "vehicleSelection") { + if (controller.bottomSheetType.value == + "vehicleSelection") { controller.bottomSheetType.value = "location"; - } else if (controller.bottomSheetType.value == "payment") { - controller.bottomSheetType.value = "vehicleSelection"; - } else if (controller.bottomSheetType.value == "conformRide") { + } else if (controller.bottomSheetType.value == + "payment") { + controller.bottomSheetType.value = + "vehicleSelection"; + } else if (controller.bottomSheetType.value == + "conformRide") { controller.bottomSheetType.value = "payment"; - } else if (controller.bottomSheetType.value == "waitingDriver" || controller.bottomSheetType.value == "driverDetails") { + } else if (controller.bottomSheetType.value == + "waitingDriver" || + controller.bottomSheetType.value == + "driverDetails") { Get.back(result: true); } else { Get.back(); } }, child: Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + borderRadius: BorderRadius.circular(30), + ), child: Padding( padding: const EdgeInsets.all(10), - child: Center(child: Icon(Icons.arrow_back_ios_new, size: 20, color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)), + child: Center( + child: Icon( + Icons.arrow_back_ios_new, + size: 20, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.greyDark50, + ), + ), ), ), ), ), controller.bottomSheetType.value == "location" - ? searchLocationBottomSheet(context, controller, isDark) - : controller.bottomSheetType.value == "vehicleSelection" + ? searchLocationBottomSheet( + context, + controller, + isDark, + ) + : controller.bottomSheetType.value == + "vehicleSelection" ? vehicleSelection(context, controller, isDark) : controller.bottomSheetType.value == "payment" ? paymentBottomSheet(context, controller, isDark) : controller.bottomSheetType.value == "conformRide" ? conformBottomSheet(context, isDark) - : controller.bottomSheetType.value == "waitingForDriver" + : controller.bottomSheetType.value == + "waitingForDriver" ? waitingDialog(context, controller, isDark) : controller.bottomSheetType.value == "driverDetails" ? driverDialog(context, controller, isDark) @@ -137,7 +213,11 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Widget searchLocationBottomSheet(BuildContext context, IntercityHomeController controller, bool isDark) { + Widget searchLocationBottomSheet( + BuildContext context, + IntercityHomeController controller, + bool isDark, + ) { return Positioned.fill( child: DraggableScrollableSheet( initialChildSize: 0.48, @@ -147,16 +227,29 @@ class IntercityHomeScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.all(16), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(35))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(35)), + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.grey400), height: 4, width: 33), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.grey400, + ), + height: 4, + width: 33, + ), SizedBox(height: 10), Stack( children: [ Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: BorderRadius.circular(12)), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: BorderRadius.circular(12), + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -164,40 +257,82 @@ class IntercityHomeScreen extends StatelessWidget { InkWell( onTap: () async { if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); - controller.sourceTextEditController.value.text = ''; + final result = await Get.to( + () => MapPickerPage(), + ); + controller.sourceTextEditController.value.text = + ''; final firstPlace = result; if (result != null) { - if (Constant.checkZoneCheck(firstPlace.coordinates.latitude, firstPlace.coordinates.longitude) == true) { + if (Constant.checkZoneCheck( + firstPlace.coordinates.latitude, + firstPlace.coordinates.longitude, + ) == + true) { final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lng = + firstPlace.coordinates.longitude; final address = firstPlace.address; - controller.sourceTextEditController.value.text = address.toString(); + controller + .sourceTextEditController + .value + .text = address.toString(); controller.setDepartureMarker(lat, lng); } else { - ShowToastDialog.showToast(ConstTexts.serviceIsUnavailable.tr()); + ShowToastDialog.showToast( + ConstTexts.serviceIsUnavailable.tr(), + ); } } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - if (Constant.checkZoneCheck(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude) == true) { - controller.sourceTextEditController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.setDepartureMarker(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude); + if (Constant.checkZoneCheck( + selectedLocationModel + .latLng! + .latitude, + selectedLocationModel + .latLng! + .longitude, + ) == + true) { + controller + .sourceTextEditController + .value + .text = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + controller.setDepartureMarker( + selectedLocationModel.latLng!.latitude, + selectedLocationModel.latLng!.longitude, + ); } else { - ShowToastDialog.showToast(ConstTexts.serviceIsUnavailable.tr()); + ShowToastDialog.showToast( + ConstTexts.serviceIsUnavailable.tr(), + ); } } }); } }, child: TextFieldWidget( - controller: controller.sourceTextEditController.value, + controller: + controller.sourceTextEditController.value, hintText: ConstTexts.pickUpLocation.tr(), enable: false, - prefix: Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Image.asset("assets/icons/pickup.png", height: 22, width: 22)), + prefix: Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Image.asset( + "assets/icons/pickup.png", + height: 22, + width: 22, + ), + ), ), ), const SizedBox(height: 10), @@ -205,34 +340,62 @@ class IntercityHomeScreen extends StatelessWidget { InkWell( onTap: () async { if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { - controller.destinationTextEditController.value.text = ''; + controller + .destinationTextEditController + .value + .text = ''; final firstPlace = result; final lat = firstPlace.coordinates.latitude; final lng = firstPlace.coordinates.longitude; final address = firstPlace.address; - controller.destinationTextEditController.value.text = address.toString(); + controller + .destinationTextEditController + .value + .text = address.toString(); controller.setDestinationMarker(lat, lng); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - controller.destinationTextEditController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.setDestinationMarker(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude); + controller + .destinationTextEditController + .value + .text = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + controller.setDestinationMarker( + selectedLocationModel.latLng!.latitude, + selectedLocationModel.latLng!.longitude, + ); } }); } }, child: TextFieldWidget( - controller: controller.destinationTextEditController.value, + controller: + controller + .destinationTextEditController + .value, // backgroundColor: AppThemeData.grey50, // borderColor: AppThemeData.grey50, hintText: ConstTexts.destinationLocation.tr(), enable: false, - prefix: const Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.radio_button_checked, color: Colors.red)), + prefix: const Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Icon( + Icons.radio_button_checked, + color: Colors.red, + ), + ), ), ), ], @@ -258,7 +421,16 @@ class IntercityHomeScreen extends StatelessWidget { ], ), SizedBox(height: 15), - Align(alignment: Alignment.centerLeft, child: Text(ConstTexts.popularDestinations.tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: AppThemeData.grey900))), + Align( + alignment: Alignment.centerLeft, + child: Text( + ConstTexts.popularDestinations.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: AppThemeData.grey900, + ), + ), + ), SizedBox( height: 120, child: Padding( @@ -269,22 +441,62 @@ class IntercityHomeScreen extends StatelessWidget { itemBuilder: (context, index) { return InkWell( onTap: () async { - if (controller.popularDestination[index].latitude != null || controller.popularDestination[index].longitude != null) { - List placeMarks = await get_cord_address.placemarkFromCoordinates( - controller.popularDestination[index].latitude ?? 0.0, - controller.popularDestination[index].longitude ?? 0.0, - ); + if (controller.popularDestination[index].latitude != + null || + controller + .popularDestination[index] + .longitude != + null) { + List placeMarks = + await get_cord_address + .placemarkFromCoordinates( + controller + .popularDestination[index] + .latitude ?? + 0.0, + controller + .popularDestination[index] + .longitude ?? + 0.0, + ); final address = - (placeMarks.first.subLocality!.isEmpty ? '' : "${placeMarks.first.subLocality}, ") + - (placeMarks.first.street!.isEmpty ? '' : "${placeMarks.first.street}, ") + - (placeMarks.first.name!.isEmpty ? '' : "${placeMarks.first.name}, ") + - (placeMarks.first.subAdministrativeArea!.isEmpty ? '' : "${placeMarks.first.subAdministrativeArea}, ") + - (placeMarks.first.administrativeArea!.isEmpty ? '' : "${placeMarks.first.administrativeArea}, ") + - (placeMarks.first.country!.isEmpty ? '' : "${placeMarks.first.country}, ") + - (placeMarks.first.postalCode!.isEmpty ? '' : "${placeMarks.first.postalCode}, "); - controller.destinationTextEditController.value.text = address; - controller.setDestinationMarker(controller.popularDestination[index].latitude ?? 0.0, controller.popularDestination[index].longitude ?? 0.0); + (placeMarks.first.subLocality!.isEmpty + ? '' + : "${placeMarks.first.subLocality}, ") + + (placeMarks.first.street!.isEmpty + ? '' + : "${placeMarks.first.street}, ") + + (placeMarks.first.name!.isEmpty + ? '' + : "${placeMarks.first.name}, ") + + (placeMarks + .first + .subAdministrativeArea! + .isEmpty + ? '' + : "${placeMarks.first.subAdministrativeArea}, ") + + (placeMarks.first.administrativeArea!.isEmpty + ? '' + : "${placeMarks.first.administrativeArea}, ") + + (placeMarks.first.country!.isEmpty + ? '' + : "${placeMarks.first.country}, ") + + (placeMarks.first.postalCode!.isEmpty + ? '' + : "${placeMarks.first.postalCode}, "); + controller + .destinationTextEditController + .value + .text = address; + controller.setDestinationMarker( + controller.popularDestination[index].latitude ?? + 0.0, + controller + .popularDestination[index] + .longitude ?? + 0.0, + ); } }, child: Padding( @@ -293,24 +505,65 @@ class IntercityHomeScreen extends StatelessWidget { children: [ CachedNetworkImage( imageUrl: - (controller.popularDestination[index].image != null && controller.popularDestination[index].image!.isNotEmpty) - ? controller.popularDestination[index].image! + (controller + .popularDestination[index] + .image != + null && + controller + .popularDestination[index] + .image! + .isNotEmpty) + ? controller + .popularDestination[index] + .image! : Constant.placeHolderImage, height: 160, width: 120, imageBuilder: - (context, imageProvider) => - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), + (context, imageProvider) => Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + 10, + ), + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: + CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData.primary300, + ), + ), + ), errorWidget: - (context, url, error) => - ClipRRect(borderRadius: BorderRadius.circular(10), child: Image.network(Constant.placeHolderImage, fit: BoxFit.cover, cacheHeight: 80, cacheWidth: 80)), + (context, url, error) => ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + Constant.placeHolderImage, + fit: BoxFit.cover, + cacheHeight: 80, + cacheWidth: 80, + ), + ), fit: BoxFit.cover, ), Positioned( left: 5, top: 80, - child: Text(controller.popularDestination[index].title.toString(), style: AppThemeData.boldTextStyle(fontSize: 15, color: AppThemeData.surface)), + child: Text( + controller.popularDestination[index].title + .toString(), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: AppThemeData.surface, + ), + ), ), ], ), @@ -322,13 +575,25 @@ class IntercityHomeScreen extends StatelessWidget { ), SizedBox(height: 10), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.continueT.tr(), onPress: () { - if (controller.sourceTextEditController.value.text.isEmpty) { - ShowToastDialog.showToast(ConstTexts.plsSelectSourceLocation.tr()); - } else if (controller.destinationTextEditController.value.text.isEmpty) { - ShowToastDialog.showToast(ConstTexts.plsSelectDestinationLocations.tr()); + if (controller + .sourceTextEditController + .value + .text + .isEmpty) { + ShowToastDialog.showToast( + ConstTexts.plsSelectSourceLocation.tr(), + ); + } else if (controller + .destinationTextEditController + .value + .text + .isEmpty) { + ShowToastDialog.showToast( + ConstTexts.plsSelectDestinationLocations.tr(), + ); } else { controller.bottomSheetType.value = "vehicleSelection"; } @@ -344,7 +609,11 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Widget vehicleSelection(BuildContext context, IntercityHomeController controller, bool isDark) { + Widget vehicleSelection( + BuildContext context, + IntercityHomeController controller, + bool isDark, + ) { return Positioned.fill( child: DraggableScrollableSheet( initialChildSize: 0.40, @@ -353,20 +622,42 @@ class IntercityHomeScreen extends StatelessWidget { expand: false, builder: (context, scrollController) { return Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: const BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.grey400), height: 4, width: 33), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.grey400, + ), + height: 4, + width: 33, + ), Align( alignment: Alignment.topLeft, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Text( - ConstTexts.selectVehicleType.tr(), - style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ConstTexts.selectVehicleType.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), textAlign: TextAlign.start, ), ), @@ -379,11 +670,13 @@ class IntercityHomeScreen extends StatelessWidget { controller: scrollController, scrollDirection: Axis.vertical, itemBuilder: (context, index) { - VehicleType vehicleType = controller.vehicleTypes[index]; + VehicleType vehicleType = + controller.vehicleTypes[index]; return Obx( () => InkWell( onTap: () { - controller.selectedVehicleType.value = controller.vehicleTypes[index]; + controller.selectedVehicleType.value = + controller.vehicleTypes[index]; }, child: Padding( padding: const EdgeInsets.only(bottom: 10), @@ -393,60 +686,130 @@ class IntercityHomeScreen extends StatelessWidget { border: Border.all( color: isDark - ? controller.selectedVehicleType.value.id == vehicleType.id + ? controller + .selectedVehicleType + .value + .id == + vehicleType.id ? Colors.white : AppThemeData.grey500 - : controller.selectedVehicleType.value.id == vehicleType.id + : controller + .selectedVehicleType + .value + .id == + vehicleType.id ? AppThemeData.grey300 : Colors.transparent, width: 1, ), color: - controller.selectedVehicleType.value.id == vehicleType.id + controller.selectedVehicleType.value.id == + vehicleType.id ? AppThemeData.grey50 : isDark ? AppThemeData.grey300 : Colors.white, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), child: Row( children: [ ClipRRect( //borderRadius: BorderRadius.circular(10), child: CachedNetworkImage( - imageUrl: vehicleType.vehicleIcon.toString(), + imageUrl: + vehicleType.vehicleIcon + .toString(), height: 60, width: 60, imageBuilder: (context, imageProvider) => - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => ClipRRect(borderRadius: BorderRadius.circular(20), child: Image.network(Constant.userPlaceHolder, fit: BoxFit.cover)), + Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 10, + ), + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: + CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), + errorWidget: + (context, url, error) => + ClipRRect( + borderRadius: + BorderRadius.circular( + 20, + ), + child: Image.network( + Constant.userPlaceHolder, + fit: BoxFit.cover, + ), + ), fit: BoxFit.cover, ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${vehicleType.name} | ${controller.distance.toStringAsFixed(2)}km", - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, letterSpacing: 1), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + letterSpacing: 1, + ), ), Padding( - padding: const EdgeInsets.only(top: 2.0), - child: Text(controller.duration.value, style: const TextStyle(fontWeight: FontWeight.w400, letterSpacing: 1)), + padding: const EdgeInsets.only( + top: 2.0, + ), + child: Text( + controller.duration.value, + style: const TextStyle( + fontWeight: FontWeight.w400, + letterSpacing: 1, + ), + ), ), ], ), ), ), Text( - Constant.amountShow(amount: controller.getAmount(vehicleType).toString()), - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, letterSpacing: 1), + Constant.amountShow( + amount: + controller + .getAmount(vehicleType) + .toString(), + ), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + letterSpacing: 1, + ), ), ], ), @@ -460,13 +823,17 @@ class IntercityHomeScreen extends StatelessWidget { ), Obx( () => RoundedButtonFill( - borderRadius: 10.r, - title: 'pay_amount'.trParams({ - 'amount': - controller.selectedVehicleType.value.id == null - ? Constant.amountShow(amount: "0.0") - : Constant.amountShow(amount: controller.getAmount(controller.selectedVehicleType.value).toString()), - }), + borderRadius: 10.r, + title: 'pay_amount'.tr(namedArgs: { + 'amount': controller.selectedVehicleType.value.id == null + ? Constant.amountShow(amount: "0.0") + : Constant.amountShow( + amount: controller + .getAmount(controller.selectedVehicleType.value) + .toString(), + ), +}), + // title: // "Pay ${controller.selectedVehicleType.value.id == null ? Constant.amountShow(amount: "0.0") : Constant.amountShow(amount: controller.getAmount(controller.selectedVehicleType.value).toString())}", onPress: () async { @@ -474,7 +841,9 @@ class IntercityHomeScreen extends StatelessWidget { controller.calculateTotalAmount(); controller.bottomSheetType.value = "payment"; } else { - ShowToastDialog.showToast(ConstTexts.plsSelectVehicleTypeFirst.tr()); + ShowToastDialog.showToast( + ConstTexts.plsSelectVehicleTypeFirst.tr(), + ); } }, color: AppThemeData.primary300, @@ -490,7 +859,11 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Widget paymentBottomSheet(BuildContext context, IntercityHomeController controller, bool isDark) { + Widget paymentBottomSheet( + BuildContext context, + IntercityHomeController controller, + bool isDark, + ) { return Positioned.fill( child: DraggableScrollableSheet( initialChildSize: 0.70, @@ -500,19 +873,37 @@ class IntercityHomeScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.selectPaymentMethod.tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + ConstTexts.selectPaymentMethod.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), GestureDetector( onTap: () { Get.back(); }, - child: Icon(Icons.close, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + child: Icon( + Icons.close, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -522,32 +913,82 @@ class IntercityHomeScreen extends StatelessWidget { padding: EdgeInsets.zero, controller: scrollController, children: [ - Text(ConstTexts.prefferedPayment.tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + ConstTexts.prefferedPayment.tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == + true || + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark100 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == + true || + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -555,7 +996,13 @@ class IntercityHomeScreen extends StatelessWidget { Text( ConstTexts.otherPaymentOptions.tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), ), const SizedBox(height: 10), ], @@ -563,32 +1010,136 @@ class IntercityHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark100 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller + .mercadoPagoModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller + .flutterWaveModel + .value + .isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -598,19 +1149,24 @@ class IntercityHomeScreen extends StatelessWidget { ), ), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.continueT.tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey900, onPress: () async { if (controller.selectedPaymentMethod.value.isEmpty) { - ShowToastDialog.showToast(ConstTexts.plsSelectPaymentMethod.tr()); + ShowToastDialog.showToast( + ConstTexts.plsSelectPaymentMethod.tr(), + ); return; } if (controller.selectedPaymentMethod.value == "wallet") { - num walletAmount = controller.userModel.value.walletAmount ?? 0; + num walletAmount = + controller.userModel.value.walletAmount ?? 0; if (walletAmount <= 0) { - ShowToastDialog.showToast(ConstTexts.insufficientWallet.tr()); + ShowToastDialog.showToast( + ConstTexts.insufficientWallet.tr(), + ); return; } } @@ -657,13 +1213,29 @@ class IntercityHomeScreen extends StatelessWidget { init: IntercityHomeController(), builder: (controller) { return Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.grey400), height: 4, width: 33), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.grey400, + ), + height: 4, + width: 33, + ), Expanded( child: ListView( controller: scrollController, @@ -673,75 +1245,178 @@ class IntercityHomeScreen extends StatelessWidget { Stack( children: [ Container( - decoration: BoxDecoration(color: isDark ? Colors.transparent : Colors.white, borderRadius: BorderRadius.circular(12)), + decoration: BoxDecoration( + color: + isDark + ? Colors.transparent + : Colors.white, + borderRadius: BorderRadius.circular(12), + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Pickup Location InkWell( onTap: () async { - if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + if (Constant.selectedMapType == + 'osm') { + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { - controller.sourceTextEditController.value.text = ''; + controller + .sourceTextEditController + .value + .text = ''; final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; - final address = firstPlace.address; - controller.sourceTextEditController.value.text = address.toString(); - controller.setDepartureMarker(lat, lng); + final lat = + firstPlace + .coordinates + .latitude; + final lng = + firstPlace + .coordinates + .longitude; + final address = + firstPlace.address; + controller + .sourceTextEditController + .value + .text = address.toString(); + controller.setDepartureMarker( + lat, + lng, + ); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to( + LocationPickerScreen(), + )!.then((value) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - controller.sourceTextEditController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.setDepartureMarker(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude); + controller + .sourceTextEditController + .value + .text = Utils.formatAddress( + selectedLocation: + selectedLocationModel, + ); + controller.setDepartureMarker( + selectedLocationModel + .latLng! + .latitude, + selectedLocationModel + .latLng! + .longitude, + ); } }); } }, child: TextFieldWidget( - controller: controller.sourceTextEditController.value, - hintText: ConstTexts.pickUpLocation.tr(), + controller: + controller + .sourceTextEditController + .value, + hintText: + ConstTexts.pickUpLocation.tr(), enable: false, - prefix: const Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.stop_circle_outlined, color: Colors.green)), + prefix: const Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Icon( + Icons.stop_circle_outlined, + color: Colors.green, + ), + ), ), ), const SizedBox(height: 10), // Destination Location InkWell( onTap: () async { - if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + if (Constant.selectedMapType == + 'osm') { + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { - controller.destinationTextEditController.value.text = ''; + controller + .destinationTextEditController + .value + .text = ''; final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; - final address = firstPlace.address; - controller.destinationTextEditController.value.text = address.toString(); - controller.setDestinationMarker(lat, lng); + final lat = + firstPlace + .coordinates + .latitude; + final lng = + firstPlace + .coordinates + .longitude; + final address = + firstPlace.address; + controller + .destinationTextEditController + .value + .text = address.toString(); + controller.setDestinationMarker( + lat, + lng, + ); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to( + LocationPickerScreen(), + )!.then((value) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - controller.destinationTextEditController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.setDestinationMarker(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude); + controller + .destinationTextEditController + .value + .text = Utils.formatAddress( + selectedLocation: + selectedLocationModel, + ); + controller.setDestinationMarker( + selectedLocationModel + .latLng! + .latitude, + selectedLocationModel + .latLng! + .longitude, + ); } }); } }, child: TextFieldWidget( - controller: controller.destinationTextEditController.value, + controller: + controller + .destinationTextEditController + .value, // backgroundColor: AppThemeData.grey50, // borderColor: AppThemeData.grey50, - hintText: ConstTexts.destinationLocation.tr(), + hintText: + ConstTexts.destinationLocation + .tr(), enable: false, - prefix: const Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.radio_button_checked, color: Colors.red)), + prefix: const Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Icon( + Icons.radio_button_checked, + color: Colors.red, + ), + ), ), ), ], @@ -759,9 +1434,15 @@ class IntercityHomeScreen extends StatelessWidget { (size) => Path() ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), + ..lineTo( + size.width / 2, + size.height, + ), + ), + child: const SizedBox( + width: 20, + height: 40, ), - child: const SizedBox(width: 20, height: 40), ), ), ], @@ -770,24 +1451,55 @@ class IntercityHomeScreen extends StatelessWidget { Row( children: [ - Expanded(child: Text(ConstTexts.promoCode.tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Expanded( + child: Text( + ConstTexts.promoCode.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), InkWell( onTap: () { - Get.to(CabCouponCodeScreen())!.then((value) { + Get.to(CabCouponCodeScreen())!.then(( + value, + ) { if (value != null) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: value); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = value; + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: value, + ); + if (couponAmount < + controller.subTotal.value) { + controller.selectedCouponModel.value = + value; controller.calculateTotalAmount(); } else { - ShowToastDialog.showToast(ConstTexts.thisOfferNotEligible.tr()); + ShowToastDialog.showToast( + ConstTexts.thisOfferNotEligible + .tr(), + ); } } }); }, child: Text( ConstTexts.viewAll.tr(), - style: AppThemeData.boldTextStyle(decoration: TextDecoration.underline, fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.boldTextStyle( + decoration: TextDecoration.underline, + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ], @@ -800,56 +1512,130 @@ class IntercityHomeScreen extends StatelessWidget { height: Responsive.height(6, context), color: AppThemeData.carRent50, child: DottedBorder( - options: RectDottedBorderOptions(dashPattern: [10, 5], strokeWidth: 1, padding: EdgeInsets.all(0), color: AppThemeData.carRent400), + options: RectDottedBorderOptions( + dashPattern: [10, 5], + strokeWidth: 1, + padding: EdgeInsets.all(0), + color: AppThemeData.carRent400, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_coupon.svg"), + SvgPicture.asset( + "assets/icons/ic_coupon.svg", + ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: TextFormField( - controller: controller.couponCodeTextEditController.value, - style: AppThemeData.semiBoldTextStyle(color: AppThemeData.parcelService500, fontSize: 16), + controller: + controller + .couponCodeTextEditController + .value, + style: + AppThemeData.semiBoldTextStyle( + color: + AppThemeData + .parcelService500, + fontSize: 16, + ), decoration: InputDecoration( border: InputBorder.none, - hintText: ConstTexts.writeCoupon.tr(), - contentPadding: EdgeInsets.only(bottom: 10), - hintStyle: AppThemeData.semiBoldTextStyle(color: AppThemeData.parcelService500, fontSize: 16), + hintText: + ConstTexts.writeCoupon.tr(), + contentPadding: EdgeInsets.only( + bottom: 10, + ), + hintStyle: + AppThemeData.semiBoldTextStyle( + color: + AppThemeData + .parcelService500, + fontSize: 16, + ), ), ), ), ), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.redeemNow.tr(), width: 27.w, fontSizes: 14, onPress: () async { if (controller.cabCouponList - .where((element) => element.code!.toLowerCase() == controller.couponCodeTextEditController.value.text.toLowerCase()) + .where( + (element) => + element.code! + .toLowerCase() == + controller + .couponCodeTextEditController + .value + .text + .toLowerCase(), + ) .isNotEmpty) { - CouponModel couponModel = controller.cabCouponList.firstWhere( - (p0) => p0.code!.toLowerCase() == controller.couponCodeTextEditController.value.text.toLowerCase(), - ); - if (couponModel.expiresAt!.toDate().isAfter(DateTime.now())) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: couponModel); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = couponModel; - controller.calculateTotalAmount(); + CouponModel + couponModel = controller + .cabCouponList + .firstWhere( + (p0) => + p0.code! + .toLowerCase() == + controller + .couponCodeTextEditController + .value + .text + .toLowerCase(), + ); + if (couponModel.expiresAt! + .toDate() + .isAfter(DateTime.now())) { + double couponAmount = + Constant.calculateDiscount( + amount: + controller + .subTotal + .value + .toString(), + offerModel: couponModel, + ); + if (couponAmount < + controller.subTotal.value) { + controller + .selectedCouponModel + .value = couponModel; + controller + .calculateTotalAmount(); controller.update(); } else { - ShowToastDialog.showToast(ConstTexts.thisOfferNotEligible.tr()); + ShowToastDialog.showToast( + ConstTexts + .thisOfferNotEligible + .tr(), + ); } } else { - ShowToastDialog.showToast(ConstTexts.couponExpired.tr()); + ShowToastDialog.showToast( + ConstTexts.couponExpired.tr(), + ); } } else { - ShowToastDialog.showToast(ConstTexts.invalidCouponCode.tr()); + ShowToastDialog.showToast( + ConstTexts.invalidCouponCode + .tr(), + ); } }, color: AppThemeData.parcelService300, @@ -866,46 +1652,121 @@ class IntercityHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(ConstTexts.orderSummary.tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + ConstTexts.orderSummary.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 8), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.subtotal.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - Constant.amountShow(amount: controller.subTotal.value.toString()), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ConstTexts.subtotal.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + Constant.amountShow( + amount: + controller.subTotal.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Row( children: [ - Text(ConstTexts.discount.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + ConstTexts.discount.tr(), + style: + AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), SizedBox(width: 5), Text( - controller.selectedCouponModel.value.id == null ? "" : "(${controller.selectedCouponModel.value.code})", - style: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.primary300), + controller + .selectedCouponModel + .value + .id == + null + ? "" + : "(${controller.selectedCouponModel.value.code})", + style: + AppThemeData.mediumTextStyle( + fontSize: 16, + color: + AppThemeData.primary300, + ), ), ], ), - Text(Constant.amountShow(amount: controller.discount.value.toString()), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.danger300)), + Text( + Constant.amountShow( + amount: + controller.discount.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: AppThemeData.danger300, + ), + ), ], ), ), @@ -917,24 +1778,56 @@ class IntercityHomeScreen extends StatelessWidget { physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (context, index) { - TaxModel taxModel = Constant.taxList[index]; + TaxModel taxModel = + Constant.taxList[index]; return Padding( - padding: const EdgeInsets.only(bottom: 5), + padding: const EdgeInsets.only( + bottom: 5, + ), child: Row( children: [ Expanded( child: Text( '${taxModel.title} (${taxModel.tax} ${taxModel.type == "Fixed" ? Constant.currencyData!.code : "%"})', textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( Constant.amountShow( - amount: Constant.calculateTax(amount: (controller.subTotal.value - controller.discount.value).toString(), taxModel: taxModel).toString(), + amount: + Constant.calculateTax( + amount: + (controller + .subTotal + .value - + controller + .discount + .value) + .toString(), + taxModel: taxModel, + ).toString(), ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), @@ -944,14 +1837,36 @@ class IntercityHomeScreen extends StatelessWidget { const Divider(), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.orderTotal.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - Constant.amountShow(amount: controller.totalAmount.value.toString()), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ConstTexts.orderTotal.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + Constant.amountShow( + amount: + controller.totalAmount.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -963,42 +1878,154 @@ class IntercityHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(10), child: Row( children: [ controller.selectedPaymentMethod.value == '' - ? cardDecorationScreen(controller, PaymentGateway.wallet, isDark, "") - : controller.selectedPaymentMethod.value == PaymentGateway.wallet.name - ? cardDecorationScreen(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png") - : controller.selectedPaymentMethod.value == PaymentGateway.cod.name - ? cardDecorationScreen(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png") - : controller.selectedPaymentMethod.value == PaymentGateway.stripe.name - ? cardDecorationScreen(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png") - : controller.selectedPaymentMethod.value == PaymentGateway.paypal.name - ? cardDecorationScreen(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payStack.name - ? cardDecorationScreen(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png") - : controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name - ? cardDecorationScreen(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png") - : controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name - ? cardDecorationScreen(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payFast.name - ? cardDecorationScreen(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png") - : controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name - ? cardDecorationScreen(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png") - : controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name - ? cardDecorationScreen(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png") - : controller.selectedPaymentMethod.value == PaymentGateway.xendit.name - ? cardDecorationScreen(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png") - : cardDecorationScreen(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"), + ? cardDecorationScreen( + controller, + PaymentGateway.wallet, + isDark, + "", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.wallet.name + ? cardDecorationScreen( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.cod.name + ? cardDecorationScreen( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.stripe.name + ? cardDecorationScreen( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.paypal.name + ? cardDecorationScreen( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.payStack.name + ? cardDecorationScreen( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.mercadoPago.name + ? cardDecorationScreen( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.flutterWave.name + ? cardDecorationScreen( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.payFast.name + ? cardDecorationScreen( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.midTrans.name + ? cardDecorationScreen( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.orangeMoney.name + ? cardDecorationScreen( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.xendit.name + ? cardDecorationScreen( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ) + : cardDecorationScreen( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), SizedBox(width: 22), Text( controller.selectedPaymentMethod.value, textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -1007,7 +2034,7 @@ class IntercityHomeScreen extends StatelessWidget { ), ), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.confirmBooking.tr(), onPress: () async { controller.placeOrder(); @@ -1026,7 +2053,11 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Widget waitingDialog(BuildContext context, IntercityHomeController controller, bool isDark) { + Widget waitingDialog( + BuildContext context, + IntercityHomeController controller, + bool isDark, + ) { return Positioned.fill( child: DraggableScrollableSheet( initialChildSize: 0.4, @@ -1035,18 +2066,40 @@ class IntercityHomeScreen extends StatelessWidget { expand: false, builder: (context, scrollController) { return Container( - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.grey400), height: 4, width: 33), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.grey400, + ), + height: 4, + width: 33, + ), SizedBox(height: 30), - Text(ConstTexts.waitingForDriver.tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + ConstTexts.waitingForDriver.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), Image.asset('assets/loader.gif', width: 250), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.cancelRide.tr(), onPress: () async { try { @@ -1059,7 +2112,9 @@ class IntercityHomeScreen extends StatelessWidget { // 2. Save to Firestore if (controller.currentOrder.value.id != null) { - await FireStoreUtils.updateCabOrder(controller.currentOrder.value); + await FireStoreUtils.updateCabOrder( + controller.currentOrder.value, + ); } // 3. Reset controller states @@ -1070,10 +2125,22 @@ class IntercityHomeScreen extends StatelessWidget { controller.routePoints.clear(); controller.sourceTextEditController.value.clear(); controller.destinationTextEditController.value.clear(); - controller.departureLatLong.value = const LatLng(0.0, 0.0); - controller.destinationLatLong.value = const LatLng(0.0, 0.0); - controller.departureLatLongOsm.value = latlong.LatLng(0.0, 0.0); - controller.destinationLatLongOsm.value = latlong.LatLng(0.0, 0.0); + controller.departureLatLong.value = const LatLng( + 0.0, + 0.0, + ); + controller.destinationLatLong.value = const LatLng( + 0.0, + 0.0, + ); + controller.departureLatLongOsm.value = latlong.LatLng( + 0.0, + 0.0, + ); + controller.destinationLatLongOsm.value = latlong.LatLng( + 0.0, + 0.0, + ); // 4. Reset user’s in-progress order if (Constant.userModel != null) { @@ -1082,12 +2149,18 @@ class IntercityHomeScreen extends StatelessWidget { } // 5. Optional feedback - ShowToastDialog.showToast(ConstTexts.riderCancelledSucces.tr()); + ShowToastDialog.showToast( + ConstTexts.riderCancelledSucces.tr(), + ); Get.back(); - CabDashboardController cabDashboardController = Get.put(CabDashboardController()); + CabDashboardController cabDashboardController = Get.put( + CabDashboardController(), + ); cabDashboardController.selectedIndex.value = 0; } catch (e) { - ShowToastDialog.showToast(ConstTexts.failedToCancel.tr()); + ShowToastDialog.showToast( + ConstTexts.failedToCancel.tr(), + ); } }, color: AppThemeData.danger300, @@ -1102,7 +2175,11 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Widget driverDialog(BuildContext context, IntercityHomeController controller, bool isDark) { + Widget driverDialog( + BuildContext context, + IntercityHomeController controller, + bool isDark, + ) { return Positioned.fill( child: DraggableScrollableSheet( initialChildSize: 0.7, @@ -1111,13 +2188,29 @@ class IntercityHomeScreen extends StatelessWidget { expand: false, builder: (context, scrollController) { return Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey700 : Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.grey400), height: 4, width: 33), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.grey400, + ), + height: 4, + width: 33, + ), Expanded( child: ListView( controller: scrollController, @@ -1127,7 +2220,11 @@ class IntercityHomeScreen extends StatelessWidget { Stack( children: [ Container( - decoration: BoxDecoration(color: isDark ? Colors.transparent : Colors.white, borderRadius: BorderRadius.circular(12)), + decoration: BoxDecoration( + color: + isDark ? Colors.transparent : Colors.white, + borderRadius: BorderRadius.circular(12), + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -1157,11 +2254,23 @@ class IntercityHomeScreen extends StatelessWidget { // } }, child: TextFieldWidget( - controller: controller.sourceTextEditController.value, + controller: + controller + .sourceTextEditController + .value, hintText: ConstTexts.pickUpLocation.tr(), enable: false, readOnly: true, - prefix: const Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.stop_circle_outlined, color: Colors.green)), + prefix: const Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Icon( + Icons.stop_circle_outlined, + color: Colors.green, + ), + ), ), ), const SizedBox(height: 10), @@ -1191,13 +2300,26 @@ class IntercityHomeScreen extends StatelessWidget { // } }, child: TextFieldWidget( - controller: controller.destinationTextEditController.value, + controller: + controller + .destinationTextEditController + .value, // backgroundColor: AppThemeData.grey50, // borderColor: AppThemeData.grey50, - hintText: ConstTexts.destinationLocation.tr(), + hintText: + ConstTexts.destinationLocation.tr(), enable: false, readOnly: true, - prefix: const Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.radio_button_checked, color: Colors.red)), + prefix: const Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Icon( + Icons.radio_button_checked, + color: Colors.red, + ), + ), ), ), ], @@ -1215,7 +2337,10 @@ class IntercityHomeScreen extends StatelessWidget { (size) => Path() ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), + ..lineTo( + size.width / 2, + size.height, + ), ), child: const SizedBox(width: 20, height: 40), ), @@ -1229,7 +2354,18 @@ class IntercityHomeScreen extends StatelessWidget { children: [ ClipRRect( borderRadius: BorderRadiusGeometry.circular(10), - child: NetworkImageWidget(imageUrl: controller.currentOrder.value.driver?.profilePictureURL ?? '', height: 70, width: 70, borderRadius: 35), + child: NetworkImageWidget( + imageUrl: + controller + .currentOrder + .value + .driver + ?.profilePictureURL ?? + '', + height: 70, + width: 70, + borderRadius: 35, + ), ), SizedBox(width: 10), Expanded( @@ -1238,22 +2374,51 @@ class IntercityHomeScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - controller.currentOrder.value.driver?.fullName() ?? '', - style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18), + controller.currentOrder.value.driver + ?.fullName() ?? + '', + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 18, + ), ), Text( "${controller.currentOrder.value.driver?.vehicleType ?? ''} | ${controller.currentOrder.value.driver?.carMakes ?? ''}", - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 14), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.greyDark700 + : AppThemeData.grey700, + fontSize: 14, + ), ), Text( - controller.currentOrder.value.driver?.carNumber ?? '', - style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 16), + controller + .currentOrder + .value + .driver + ?.carNumber ?? + '', + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData.greyDark700 + : AppThemeData.grey700, + fontSize: 16, + ), ), ], ), ), RoundedButtonBorder( - title: controller.driverModel.value.averageRating.toStringAsFixed(1) ?? '', + title: + controller.driverModel.value.averageRating + .toStringAsFixed(1) ?? + '', width: 20, height: 3.5, radius: 10, @@ -1262,7 +2427,9 @@ class IntercityHomeScreen extends StatelessWidget { textColor: AppThemeData.warning400, borderColor: AppThemeData.warning400, color: AppThemeData.warning50, - icon: SvgPicture.asset("assets/icons/ic_start.svg"), + icon: SvgPicture.asset( + "assets/icons/ic_start.svg", + ), onPress: () {}, ), ], @@ -1271,37 +2438,98 @@ class IntercityHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(ConstTexts.orderSummary.tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + ConstTexts.orderSummary.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 8), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.subtotal.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - Constant.amountShow(amount: controller.subTotal.value.toString()), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ConstTexts.subtotal.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + Constant.amountShow( + amount: + controller.subTotal.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.discount.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(Constant.amountShow(amount: controller.discount.value.toString()), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.danger300)), + Text( + ConstTexts.discount.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + Constant.amountShow( + amount: + controller.discount.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: AppThemeData.danger300, + ), + ), ], ), ), @@ -1322,15 +2550,38 @@ class IntercityHomeScreen extends StatelessWidget { child: Text( '${taxModel.title} (${taxModel.tax} ${taxModel.type == "Fixed" ? Constant.currencyData!.code : "%"})', textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), Text( Constant.amountShow( - amount: Constant.calculateTax(amount: (controller.subTotal.value - controller.discount.value).toString(), taxModel: taxModel).toString(), + amount: + Constant.calculateTax( + amount: + (controller + .subTotal + .value - + controller + .discount + .value) + .toString(), + taxModel: taxModel, + ).toString(), ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -1340,14 +2591,36 @@ class IntercityHomeScreen extends StatelessWidget { const Divider(), Padding( - padding: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.symmetric( + vertical: 4, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.orderTotal.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - Constant.amountShow(amount: controller.totalAmount.value.toString()), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ConstTexts.orderTotal.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + Constant.amountShow( + amount: + controller.totalAmount.value + .toString(), + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -1359,8 +2632,16 @@ class IntercityHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(10), child: InkWell( @@ -1369,34 +2650,111 @@ class IntercityHomeScreen extends StatelessWidget { }, child: Row( children: [ - controller.selectedPaymentMethod.value == PaymentGateway.wallet.name - ? cardDecorationScreen(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png") - : controller.selectedPaymentMethod.value == PaymentGateway.cod.name - ? cardDecorationScreen(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png") - : controller.selectedPaymentMethod.value == PaymentGateway.stripe.name - ? cardDecorationScreen(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png") - : controller.selectedPaymentMethod.value == PaymentGateway.paypal.name - ? cardDecorationScreen(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payStack.name - ? cardDecorationScreen(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png") - : controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name - ? cardDecorationScreen(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png") - : controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name - ? cardDecorationScreen(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payFast.name - ? cardDecorationScreen(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png") - : controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name - ? cardDecorationScreen(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png") - : controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name - ? cardDecorationScreen(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png") - : controller.selectedPaymentMethod.value == PaymentGateway.xendit.name - ? cardDecorationScreen(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png") - : cardDecorationScreen(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"), + controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name + ? cardDecorationScreen( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.cod.name + ? cardDecorationScreen( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name + ? cardDecorationScreen( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name + ? cardDecorationScreen( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name + ? cardDecorationScreen( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name + ? cardDecorationScreen( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name + ? cardDecorationScreen( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name + ? cardDecorationScreen( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name + ? cardDecorationScreen( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name + ? cardDecorationScreen( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ) + : controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name + ? cardDecorationScreen( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ) + : cardDecorationScreen( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), SizedBox(width: 22), Text( controller.selectedPaymentMethod.value, textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -1404,48 +2762,77 @@ class IntercityHomeScreen extends StatelessWidget { ), const SizedBox(height: 20), Obx(() { - if (controller.currentOrder.value.status == Constant.orderInTransit) { + if (controller.currentOrder.value.status == + Constant.orderInTransit) { return Column( children: [ RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "SOS", color: Colors.red.withValues(alpha: 0.50), textColor: AppThemeData.grey50, isCenter: true, icon: Icon(Icons.call, color: Colors.white), onPress: () async { - ShowToastDialog.showLoader(ConstTexts.pleaseWait.tr()); + ShowToastDialog.showLoader( + ConstTexts.pleaseWait.tr(), + ); - LocationData location = await controller.currentLocation.value.getLocation(); + LocationData location = + await controller.currentLocation.value + .getLocation(); - await FireStoreUtils.getSOS(controller.currentOrder.value.id ?? '').then((value) async { + await FireStoreUtils.getSOS( + controller.currentOrder.value.id ?? '', + ).then((value) async { if (value == false) { - await FireStoreUtils.setSos(controller.currentOrder.value.id ?? '', UserLocation(latitude: location.latitude!, longitude: location.longitude!)).then((value) { + await FireStoreUtils.setSos( + controller.currentOrder.value.id ?? + '', + UserLocation( + latitude: location.latitude!, + longitude: location.longitude!, + ), + ).then((value) { ShowToastDialog.closeLoader(); - ScaffoldMessenger.of(context).showSnackBar( + ScaffoldMessenger.of( + context, + ).showSnackBar( SnackBar( content: Builder( builder: (context) { - return Text(ConstTexts.yourSosRequest.tr()); + return Text( + ConstTexts.yourSosRequest + .tr(), + ); }, ), backgroundColor: Colors.green, - duration: const Duration(seconds: 3), + duration: const Duration( + seconds: 3, + ), ), ); }); } else { ShowToastDialog.closeLoader(); - ScaffoldMessenger.of(context).showSnackBar( + ScaffoldMessenger.of( + context, + ).showSnackBar( SnackBar( content: Builder( builder: (context) { - return Text(ConstTexts.yourSosrequestAlreadySubmitted.tr()); + return Text( + ConstTexts + .yourSosrequestAlreadySubmitted + .tr(), + ); }, ), backgroundColor: Colors.red, - duration: const Duration(seconds: 3), + duration: const Duration( + seconds: 3, + ), ), ); } @@ -1463,45 +2850,100 @@ class IntercityHomeScreen extends StatelessWidget { ), ), Obx(() { - if (controller.currentOrder.value.status == Constant.orderInTransit && controller.currentOrder.value.paymentStatus == false) { + if (controller.currentOrder.value.status == + Constant.orderInTransit && + controller.currentOrder.value.paymentStatus == false) { return RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.payNow.tr(), onPress: () async { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.totalAmount.value.toString(), context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.totalAmount.value.toString(), + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.cod.name) { controller.completeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name) { controller.completeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.totalAmount.value.toString()), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast(ConstTexts.somethingWentWrong.tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.totalAmount.value.toString(), orderId: result.id); - } - }); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.totalAmount.value.toString(), + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + ConstTexts.somethingWentWrong.tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: + controller.totalAmount.value + .toString(), + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast(ConstTexts.plsSelectPaymentMethod.tr()); + ShowToastDialog.showToast( + ConstTexts.plsSelectPaymentMethod.tr(), + ); } }, color: AppThemeData.primary300, @@ -1520,19 +2962,42 @@ class IntercityHomeScreen extends StatelessWidget { ); } - Padding cardDecorationScreen(IntercityHomeController controller, PaymentGateway value, isDark, String image) { + Padding cardDecorationScreen( + IntercityHomeController controller, + PaymentGateway value, + isDark, + String image, + ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: Container( width: 40, height: 40, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: image == '' ? Container(color: isDark ? AppThemeData.grey800 : AppThemeData.grey100) : Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), + child: + image == '' + ? Container( + color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + ) + : Image.asset(image), + ), ), ); } - Obx cardDecoration(IntercityHomeController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + IntercityHomeController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -1547,8 +3012,21 @@ class IntercityHomeScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -1559,12 +3037,34 @@ class IntercityHomeScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: controller.userModel.value.walletAmount == null ? '0.0' : controller.userModel.value.walletAmount.toString()), + Constant.amountShow( + amount: + controller.userModel.value.walletAmount == + null + ? '0.0' + : controller + .userModel + .value + .walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -1573,14 +3073,23 @@ class IntercityHomeScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/cab_service_screens/cab_booking_screen.dart b/lib/screen_ui/cab_service_screens/cab_booking_screen.dart index 0df9bdd..56de16c 100644 --- a/lib/screen_ui/cab_service_screens/cab_booking_screen.dart +++ b/lib/screen_ui/cab_service_screens/cab_booking_screen.dart @@ -18,7 +18,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter_map/flutter_map.dart' as flutterMap; import 'package:latlong2/latlong.dart' as latlong; @@ -668,21 +668,16 @@ class CabBookingScreen extends StatelessWidget { child: Obx( () => RoundedButtonFill( borderRadius: 10.r, - title: 'pay_amount'.trParams({ - 'amount': - controller.selectedVehicleType.value.id == null - ? Constant.amountShow(amount: "0.0") - : Constant.amountShow( - amount: - controller - .getAmount( - controller - .selectedVehicleType - .value, - ) - .toString(), - ), - }), + title: 'pay_amount'.tr(namedArgs: { + 'amount': controller.selectedVehicleType.value.id == null + ? Constant.amountShow(amount: "0.0") + : Constant.amountShow( + amount: controller + .getAmount(controller.selectedVehicleType.value) + .toString(), + ), +}), + onPress: () async { if (controller.selectedVehicleType.value.id != null) { controller.calculateTotalAmount(); @@ -1927,7 +1922,9 @@ class CabBookingScreen extends StatelessWidget { ); cabDashboardController.selectedIndex.value = 0; } catch (e) { - ShowToastDialog.showToast(ConstTexts.failedToCancel.tr()); + ShowToastDialog.showToast( + ConstTexts.failedToCancel.tr(), + ); } }, ), @@ -2069,7 +2066,8 @@ class CabBookingScreen extends StatelessWidget { .value, // backgroundColor: AppThemeData.grey50, // borderColor: AppThemeData.grey50, - hintText: ConstTexts.destinationLocation.tr(), + hintText: + ConstTexts.destinationLocation.tr(), enable: false, readOnly: true, prefix: const Padding( @@ -2282,7 +2280,7 @@ class CabBookingScreen extends StatelessWidget { InkWell( onTap: () async { ShowToastDialog.showLoader( - ConstTexts.pleaseWait.tr(), + ConstTexts.pleaseWait.tr(), ); UserModel? customer = @@ -2621,8 +2619,7 @@ class CabBookingScreen extends StatelessWidget { children: [ Expanded( child: Text( - '${taxModel.title} (${taxModel.tax} ${taxModel.type == "Fixed" ? Constant.currencyData!.code : "%"})' - , + '${taxModel.title} (${taxModel.tax} ${taxModel.type == "Fixed" ? Constant.currencyData!.code : "%"})', textAlign: TextAlign.start, style: AppThemeData.mediumTextStyle( fontSize: 14, @@ -2720,7 +2717,9 @@ class CabBookingScreen extends StatelessWidget { isCenter: true, icon: const Icon(Icons.call, color: Colors.white), onPress: () async { - ShowToastDialog.showLoader(ConstTexts.pleaseWait.tr()); + ShowToastDialog.showLoader( + ConstTexts.pleaseWait.tr(), + ); LocationData location = await controller.currentLocation.value @@ -2741,8 +2740,7 @@ class CabBookingScreen extends StatelessWidget { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - ConstTexts.yourSosRequest.tr() - + ConstTexts.yourSosRequest.tr(), ), backgroundColor: Colors.green, duration: Duration(seconds: 3), @@ -2754,7 +2752,9 @@ class CabBookingScreen extends StatelessWidget { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - ConstTexts.yourSosrequestAlreadySubmitted.tr() + ConstTexts + .yourSosrequestAlreadySubmitted + .tr(), ), backgroundColor: Colors.red, duration: Duration(seconds: 3), @@ -2822,7 +2822,8 @@ class CabBookingScreen extends StatelessWidget { Constant.userModel!.walletAmount! < controller.totalAmount.value) { ShowToastDialog.showToast( - ConstTexts.youDoNothaveSufficientwalletBalance.tr() + ConstTexts.youDoNothaveSufficientwalletBalance + .tr(), ); } else { controller.completeOrder(); @@ -2858,8 +2859,7 @@ class CabBookingScreen extends StatelessWidget { if (value == null) { Get.back(); ShowToastDialog.showToast( - - ConstTexts.somethingWentWrong.tr() + ConstTexts.somethingWentWrong.tr(), ); } else { CreateRazorPayOrderModel result = value; @@ -2873,7 +2873,7 @@ class CabBookingScreen extends StatelessWidget { }); } else { ShowToastDialog.showToast( - ConstTexts.plsSelectPaymentMethod.tr(), + ConstTexts.plsSelectPaymentMethod.tr(), ); } }, diff --git a/lib/screen_ui/cab_service_screens/cab_coupon_code_screen.dart b/lib/screen_ui/cab_service_screens/cab_coupon_code_screen.dart index 251c102..c74bdb0 100644 --- a/lib/screen_ui/cab_service_screens/cab_coupon_code_screen.dart +++ b/lib/screen_ui/cab_service_screens/cab_coupon_code_screen.dart @@ -9,7 +9,7 @@ import 'package:customer/widget/my_separator.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class CabCouponCodeScreen extends StatelessWidget { const CabCouponCodeScreen({super.key}); @@ -34,12 +34,30 @@ class CabCouponCodeScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text(ConstTexts.coupon.tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + ConstTexts.coupon.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -48,24 +66,44 @@ class CabCouponCodeScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : controller.cabCouponList.isEmpty - ? Constant.showEmptyView(message: ConstTexts.couponNotFound.tr()) + ? Constant.showEmptyView( + message: ConstTexts.couponNotFound.tr(), + ) : ListView.builder( shrinkWrap: true, itemCount: controller.cabCouponList.length, itemBuilder: (context, index) { CouponModel couponModel = controller.cabCouponList[index]; return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Container( height: Responsive.height(16, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), child: Stack( children: [ - Image.asset("assets/images/ic_coupon_image.png", height: Responsive.height(16, context), fit: BoxFit.fill), + Image.asset( + "assets/images/ic_coupon_image.png", + height: Responsive.height(16, context), + fit: BoxFit.fill, + ), Padding( padding: const EdgeInsets.only(left: 10), child: Align( @@ -75,7 +113,14 @@ class CabCouponCodeScreen extends StatelessWidget { child: Text( "${couponModel.discountType == "Fix Price" ? Constant.amountShow(amount: couponModel.discount) : "${couponModel.discount}%"} ${'Off'.tr}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), ), ), @@ -85,24 +130,53 @@ class CabCouponCodeScreen extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(6), color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + options: + RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular( + 6, + ), + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), child: Text( "${couponModel.code}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), ), ), ), - const Expanded(child: SizedBox(height: 10)), + const Expanded( + child: SizedBox(height: 10), + ), InkWell( onTap: () { Get.back(result: couponModel); @@ -110,18 +184,38 @@ class CabCouponCodeScreen extends StatelessWidget { child: Text( ConstTexts.tapToApply.tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ], ), const SizedBox(height: 20), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 20), Text( "${couponModel.description}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), diff --git a/lib/screen_ui/cab_service_screens/cab_dashboard_screen.dart b/lib/screen_ui/cab_service_screens/cab_dashboard_screen.dart index 9f322af..2e29d07 100644 --- a/lib/screen_ui/cab_service_screens/cab_dashboard_screen.dart +++ b/lib/screen_ui/cab_service_screens/cab_dashboard_screen.dart @@ -7,7 +7,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class CabDashboardScreen extends StatelessWidget { const CabDashboardScreen({super.key}); diff --git a/lib/screen_ui/cab_service_screens/cab_home_screen.dart b/lib/screen_ui/cab_service_screens/cab_home_screen.dart index c5e981b..bf9e6d9 100644 --- a/lib/screen_ui/cab_service_screens/cab_home_screen.dart +++ b/lib/screen_ui/cab_service_screens/cab_home_screen.dart @@ -10,7 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'Intercity_home_screen.dart'; import 'cab_booking_screen.dart'; @@ -123,7 +123,7 @@ class CabHomeScreen extends HookWidget { CrossAxisAlignment.start, children: [ Text( - ConstTexts.everyRideVerified.tr(), + ConstTexts.everyRideVerified.tr(), style: AppThemeData.boldTextStyle( color: isDark @@ -133,8 +133,7 @@ class CabHomeScreen extends HookWidget { ), ), Text( - ConstTexts.allDriversIDCheck - .tr(), + ConstTexts.allDriversIDCheck.tr(), style: AppThemeData.mediumTextStyle( color: isDark diff --git a/lib/screen_ui/cab_service_screens/cab_order_details.dart b/lib/screen_ui/cab_service_screens/cab_order_details.dart index 1c2a5c2..1e3b71a 100644 --- a/lib/screen_ui/cab_service_screens/cab_order_details.dart +++ b/lib/screen_ui/cab_service_screens/cab_order_details.dart @@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/cab_order_details_controller.dart'; import '../../controllers/theme_controller.dart'; diff --git a/lib/screen_ui/cab_service_screens/cab_review_screen.dart b/lib/screen_ui/cab_service_screens/cab_review_screen.dart index e39a593..ef6ee21 100644 --- a/lib/screen_ui/cab_service_screens/cab_review_screen.dart +++ b/lib/screen_ui/cab_service_screens/cab_review_screen.dart @@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; diff --git a/lib/screen_ui/cab_service_screens/complain_screen.dart b/lib/screen_ui/cab_service_screens/complain_screen.dart index 94402a8..b3019ce 100644 --- a/lib/screen_ui/cab_service_screens/complain_screen.dart +++ b/lib/screen_ui/cab_service_screens/complain_screen.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/const_texts.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/complain_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; @@ -35,12 +35,27 @@ class ComplainScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: const Center(child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20)), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: const Center( + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), ), ), const SizedBox(width: 10), - Text(ConstTexts.complain.tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + ConstTexts.complain.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -52,11 +67,30 @@ class ComplainScreen extends StatelessWidget { padding: const EdgeInsets.all(16), child: Column( children: [ - Obx(() => TextFieldWidget(title: ConstTexts.title.tr(), hintText: ConstTexts.title.tr(), controller: controller.title.value)), + Obx( + () => TextFieldWidget( + title: ConstTexts.title.tr(), + hintText: ConstTexts.title.tr(), + controller: controller.title.value, + ), + ), const SizedBox(height: 10), - Obx(() => TextFieldWidget(title:ConstTexts.complain.tr(), hintText: ConstTexts.typeDescription.tr(), controller: controller.comment.value, maxLine: 8)), + Obx( + () => TextFieldWidget( + title: ConstTexts.complain.tr(), + hintText: ConstTexts.typeDescription.tr(), + controller: controller.comment.value, + maxLine: 8, + ), + ), const SizedBox(height: 20), - RoundedButtonFill( borderRadius: 10.r,title: ConstTexts.save.tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () => controller.submitComplain()), + RoundedButtonFill( + borderRadius: 10.r, + title: ConstTexts.save.tr(), + color: AppThemeData.primary300, + textColor: AppThemeData.grey50, + onPress: () => controller.submitComplain(), + ), ], ), ), diff --git a/lib/screen_ui/cab_service_screens/my_cab_booking_screen.dart b/lib/screen_ui/cab_service_screens/my_cab_booking_screen.dart index 5a85e86..de98f82 100644 --- a/lib/screen_ui/cab_service_screens/my_cab_booking_screen.dart +++ b/lib/screen_ui/cab_service_screens/my_cab_booking_screen.dart @@ -9,7 +9,7 @@ import 'package:customer/themes/show_toast_dialog.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/my_cab_booking_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -33,14 +33,27 @@ class MyCabBookingScreen extends StatelessWidget { // length: controller.tabTitles.length, // initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value), length: controller.tabKeys.length, - initialIndex: controller.tabKeys.indexOf(controller.selectedTab.value), + initialIndex: controller.tabKeys.indexOf( + controller.selectedTab.value, + ), child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: AppThemeData.primary300, title: Padding( padding: const EdgeInsets.only(bottom: 10), - child: Row(children: [const SizedBox(width: 10), Text(ConstTexts.rideHistory.tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900))]), + child: Row( + children: [ + const SizedBox(width: 10), + Text( + ConstTexts.rideHistory.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + ], + ), ), bottom: PreferredSize( preferredSize: const Size.fromHeight(48), @@ -53,7 +66,9 @@ class MyCabBookingScreen extends StatelessWidget { labelColor: AppThemeData.taxiBooking500, unselectedLabelColor: AppThemeData.taxiBooking500, labelStyle: AppThemeData.boldTextStyle(fontSize: 14), - unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 14), + unselectedLabelStyle: AppThemeData.mediumTextStyle( + fontSize: 14, + ), tabs: controller.tabKeys .map( @@ -63,7 +78,9 @@ class MyCabBookingScreen extends StatelessWidget { child: Text( controller.getLocalizedTabTitle(key), textAlign: TextAlign.center, - overflow: TextOverflow.visible, // 👈 show full text + overflow: + TextOverflow + .visible, // 👈 show full text ), ), ), @@ -83,16 +100,33 @@ class MyCabBookingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text(ConstTexts.plsLoginToAcc.tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + ConstTexts.plsLoginToAcc.tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( ConstTexts.youAreNotLoggedIn.tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.login.tr(), width: 55, height: 5.5, @@ -111,7 +145,17 @@ class MyCabBookingScreen extends StatelessWidget { final orders = controller.getOrdersForTab(title); if (orders.isEmpty) { - return Center(child: Text(ConstTexts.noOrderfound.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))); + return Center( + child: Text( + ConstTexts.noOrderfound.tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ); } return ListView.builder( @@ -121,74 +165,150 @@ class MyCabBookingScreen extends StatelessWidget { CabOrderModel order = orders[index]; return GestureDetector( onTap: () { - Get.to(() => CabOrderDetails(), arguments: {"cabOrderModel": order}); + Get.to( + () => CabOrderDetails(), + arguments: {"cabOrderModel": order}, + ); }, child: Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, borderRadius: BorderRadius.circular(15), - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${'Booking Date:'.tr} ${controller.formatDate(order.scheduleDateTime!)}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 18, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Column( children: [ - Icon(Icons.stop_circle_outlined, color: Colors.green), - DottedBorder( - options: CustomPathDottedBorderOptions( - color: Colors.grey.shade400, - strokeWidth: 2, - dashPattern: [4, 4], - customPath: - (size) => - Path() - ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), - ), - child: const SizedBox(width: 20, height: 55), + Icon( + Icons.stop_circle_outlined, + color: Colors.green, + ), + DottedBorder( + options: + CustomPathDottedBorderOptions( + color: + Colors + .grey + .shade400, + strokeWidth: 2, + dashPattern: [4, 4], + customPath: + (size) => + Path() + ..moveTo( + size.width / + 2, + 0, + ) + ..lineTo( + size.width / + 2, + size.height, + ), + ), + child: const SizedBox( + width: 20, + height: 55, + ), + ), + Icon( + Icons.radio_button_checked, + color: Colors.red, ), - Icon(Icons.radio_button_checked, color: Colors.red), ], ), const SizedBox(width: 12), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ // Source Location Name Expanded( child: Text( - order.sourceLocationName.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + order + .sourceLocationName + .toString(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), maxLines: 2, - overflow: TextOverflow.ellipsis, + overflow: + TextOverflow + .ellipsis, ), ), const SizedBox(width: 8), Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AppThemeData.warning300, width: 1), - color: AppThemeData.warning50, + borderRadius: + BorderRadius.circular( + 10, + ), + border: Border.all( + color: + AppThemeData + .warning300, + width: 1, + ), + color: + AppThemeData + .warning50, ), - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + padding: + const EdgeInsets.symmetric( + vertical: 8, + horizontal: 12, + ), child: Text( - order.status.toString(), - style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.warning500), - overflow: TextOverflow.ellipsis, + order.status + .toString(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + AppThemeData + .warning500, + ), + overflow: + TextOverflow + .ellipsis, ), ), ], @@ -196,46 +316,114 @@ class MyCabBookingScreen extends StatelessWidget { SizedBox(height: 15), DottedBorder( options: CustomPathDottedBorderOptions( - color: Colors.grey.shade400, + color: + Colors.grey.shade400, strokeWidth: 2, dashPattern: [4, 4], customPath: (size) => Path() - ..moveTo(0, size.height / 2) // start from left center - ..lineTo(size.width, size.height / 2), // draw to right center + ..moveTo( + 0, + size.height / + 2, + ) // start from left center + ..lineTo( + size.width, + size.height / + 2, + ), // draw to right center + ), + child: const SizedBox( + width: 295, + height: 3, ), - child: const SizedBox(width: 295, height: 3), ), SizedBox(height: 15), Text( - order.destinationLocationName.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + order + .destinationLocationName + .toString(), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), ], ), - if (Constant.isEnableOTPTripStart == true) + if (Constant.isEnableOTPTripStart == + true) Row( //mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Text("Otp :", style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + "Otp :", + style: + AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark800 + : AppThemeData + .grey800, + ), + ), SizedBox(width: 5), - Text(order.otpCode ?? '', style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + order.otpCode ?? '', + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), ], ), - if (order.status == Constant.orderInTransit && order.paymentStatus == false) SizedBox(height: 14), - order.status == Constant.orderInTransit && order.paymentStatus == false + if (order.status == + Constant.orderInTransit && + order.paymentStatus == false) + SizedBox(height: 14), + order.status == + Constant.orderInTransit && + order.paymentStatus == false ? RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.payNow.tr(), onPress: () async { - controller.selectedPaymentMethod.value = order.paymentMethod.toString(); - controller.calculateTotalAmount(order); - Get.bottomSheet(paymentBottomSheet(context, controller, isDark), isScrollControlled: true, backgroundColor: Colors.transparent); + controller + .selectedPaymentMethod + .value = order.paymentMethod + .toString(); + controller.calculateTotalAmount( + order, + ); + Get.bottomSheet( + paymentBottomSheet( + context, + controller, + isDark, + ), + isScrollControlled: true, + backgroundColor: + Colors.transparent, + ); }, color: AppThemeData.primary300, textColor: AppThemeData.grey900, @@ -255,7 +443,11 @@ class MyCabBookingScreen extends StatelessWidget { ); } - Widget paymentBottomSheet(BuildContext context, MyCabBookingController controller, bool isDark) { + Widget paymentBottomSheet( + BuildContext context, + MyCabBookingController controller, + bool isDark, + ) { return DraggableScrollableSheet( initialChildSize: 0.70, // Start height @@ -268,14 +460,26 @@ class MyCabBookingScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey500 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey500 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(ConstTexts.selectPaymentMethod.tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + ConstTexts.selectPaymentMethod.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), GestureDetector( onTap: () { Get.back(); @@ -290,40 +494,88 @@ class MyCabBookingScreen extends StatelessWidget { padding: EdgeInsets.zero, controller: scrollController, children: [ - Text(ConstTexts.prefferedPayment.tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + ConstTexts.prefferedPayment.tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), Text( - ConstTexts.otherPaymentOptions.tr(), + ConstTexts.otherPaymentOptions.tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), ), const SizedBox(height: 10), ], @@ -331,32 +583,129 @@ class MyCabBookingScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -366,52 +715,109 @@ class MyCabBookingScreen extends StatelessWidget { ), ), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: ConstTexts.continueT.tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey900, onPress: () async { if (controller.selectedPaymentMethod.value.isEmpty) { - ShowToastDialog.showToast(ConstTexts.plsSelectPaymentMethod.tr()); + ShowToastDialog.showToast( + ConstTexts.plsSelectPaymentMethod.tr(), + ); } else { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.totalAmount.value.toString(), context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.totalAmount.value.toString(), + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.cod.name) { controller.completeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { - if (Constant.userModel!.walletAmount == null || Constant.userModel!.walletAmount! < controller.totalAmount.value) { - ShowToastDialog.showToast(ConstTexts.youDoNothaveSufficientwalletBalance.tr()); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name) { + if (Constant.userModel!.walletAmount == null || + Constant.userModel!.walletAmount! < + controller.totalAmount.value) { + ShowToastDialog.showToast( + ConstTexts.youDoNothaveSufficientwalletBalance.tr(), + ); } else { controller.completeOrder(); } - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.totalAmount.value.toString()), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast(ConstTexts.somethingWentWrong.tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.totalAmount.value.toString(), orderId: result.id); - } - }); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.totalAmount.value.toString(), + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + ConstTexts.somethingWentWrong.tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: controller.totalAmount.value.toString(), + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast(ConstTexts.plsSelectPaymentMethod.tr()); + ShowToastDialog.showToast( + ConstTexts.plsSelectPaymentMethod.tr(), + ); } } }, @@ -423,7 +829,12 @@ class MyCabBookingScreen extends StatelessWidget { ); } - Obx cardDecoration(MyCabBookingController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + MyCabBookingController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -438,8 +849,21 @@ class MyCabBookingScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -450,12 +874,30 @@ class MyCabBookingScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: Constant.userModel!.walletAmount == null ? '0.0' : Constant.userModel!.walletAmount.toString()), + Constant.amountShow( + amount: + Constant.userModel!.walletAmount == null + ? '0.0' + : Constant.userModel!.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -464,14 +906,23 @@ class MyCabBookingScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/ecommarce/all_brand_product_screen.dart b/lib/screen_ui/ecommarce/all_brand_product_screen.dart index c50aa39..0545863 100644 --- a/lib/screen_ui/ecommarce/all_brand_product_screen.dart +++ b/lib/screen_ui/ecommarce/all_brand_product_screen.dart @@ -9,7 +9,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/responsive.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AllBrandProductScreen extends StatelessWidget { const AllBrandProductScreen({super.key}); @@ -22,23 +22,41 @@ class AllBrandProductScreen extends StatelessWidget { init: AllBrandProductController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: GridView.builder( shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 3.5 / 6, crossAxisSpacing: 10), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + childAspectRatio: 3.5 / 6, + crossAxisSpacing: 10, + ), padding: EdgeInsets.zero, - itemCount: controller.productList.length, + itemCount: controller.productList.length, itemBuilder: (context, index) { - ProductModel productModel = controller.productList[index]; + ProductModel productModel = + controller.productList[index]; return FutureBuilder( - future: FireStoreUtils.getVendorById(productModel.vendorID.toString()), + future: FireStoreUtils.getVendorById( + productModel.vendorID.toString(), + ), builder: (context, vendorSnapshot) { - if (!vendorSnapshot.hasData || vendorSnapshot.connectionState == ConnectionState.waiting) { + if (!vendorSnapshot.hasData || + vendorSnapshot.connectionState == + ConnectionState.waiting) { return const SizedBox(); // Show placeholder or loader } VendorModel? vendorModel = vendorSnapshot.data; @@ -48,34 +66,78 @@ class AllBrandProductScreen extends StatelessWidget { List selectedIndexVariants = []; List selectedIndexArray = []; if (productModel.itemAttribute != null) { - if (productModel.itemAttribute!.attributes!.isNotEmpty) { - for (var element in productModel.itemAttribute!.attributes!) { + if (productModel + .itemAttribute! + .attributes! + .isNotEmpty) { + for (var element + in productModel + .itemAttribute! + .attributes!) { if (element.attributeOptions!.isNotEmpty) { selectedVariants.add( - productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString(), + productModel + .itemAttribute! + .attributes![productModel + .itemAttribute! + .attributes! + .indexOf(element)] + .attributeOptions![0] + .toString(), ); selectedIndexVariants.add( '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', ); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedIndexArray.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { + if (productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .isNotEmpty) { price = Constant.productCommissionPrice( vendorModel!, - productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0', + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', ); disPrice = "0"; } } else { - price = Constant.productCommissionPrice(vendorModel!, productModel.price.toString()); - disPrice = double.parse(productModel.disPrice.toString()) <= 0 ? "0" : Constant.productCommissionPrice(vendorModel, productModel.disPrice.toString()); + price = Constant.productCommissionPrice( + vendorModel!, + productModel.price.toString(), + ); + disPrice = + double.parse( + productModel.disPrice.toString(), + ) <= + 0 + ? "0" + : Constant.productCommissionPrice( + vendorModel, + productModel.disPrice.toString(), + ); } return GestureDetector( onTap: () async { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -85,47 +147,108 @@ class AllBrandProductScreen extends StatelessWidget { child: SizedBox( height: 90, width: Responsive.width(100, context), - child: NetworkImageWidget(imageUrl: productModel.photo.toString(), fit: BoxFit.cover), + child: NetworkImageWidget( + imageUrl: productModel.photo.toString(), + fit: BoxFit.cover, + ), ), ), Column( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( productModel.name!.capitalizeString(), textAlign: TextAlign.start, maxLines: 1, - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), disPrice == "" || disPrice == "0" - ? Text(Constant.amountShow(amount: price), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.primary300)) + ? Text( + Constant.amountShow(amount: price), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData.primary300, + ), + ) : Row( children: [ Text( - Constant.amountShow(amount: price), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: Colors.grey, decoration: TextDecoration.lineThrough), + Constant.amountShow( + amount: price, + ), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: Colors.grey, + decoration: + TextDecoration + .lineThrough, + ), ), const SizedBox(width: 5), Text( - Constant.amountShow(amount: disPrice), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: disPrice, + ), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.warning50 + : AppThemeData.warning50, + borderRadius: BorderRadius.circular( + 30, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.star, size: 18, color: AppThemeData.warning400), + Icon( + Icons.star, + size: 18, + color: AppThemeData.warning400, + ), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount.toString(), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsSum})", - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: AppThemeData.warning400), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + AppThemeData + .warning400, + ), ), ], ), diff --git a/lib/screen_ui/ecommarce/all_category_product_screen.dart b/lib/screen_ui/ecommarce/all_category_product_screen.dart index 16d9658..30afacd 100644 --- a/lib/screen_ui/ecommarce/all_category_product_screen.dart +++ b/lib/screen_ui/ecommarce/all_category_product_screen.dart @@ -9,7 +9,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/responsive.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AllCategoryProductScreen extends StatelessWidget { const AllCategoryProductScreen({super.key}); @@ -22,23 +22,41 @@ class AllCategoryProductScreen extends StatelessWidget { init: AllCategoryProductController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: GridView.builder( shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 3.5 / 6, crossAxisSpacing: 10), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + childAspectRatio: 3.5 / 6, + crossAxisSpacing: 10, + ), padding: EdgeInsets.zero, itemCount: controller.productList.length, itemBuilder: (context, index) { - ProductModel productModel = controller.productList[index]; + ProductModel productModel = + controller.productList[index]; return FutureBuilder( - future: FireStoreUtils.getVendorById(productModel.vendorID.toString()), + future: FireStoreUtils.getVendorById( + productModel.vendorID.toString(), + ), builder: (context, vendorSnapshot) { - if (!vendorSnapshot.hasData || vendorSnapshot.connectionState == ConnectionState.waiting) { + if (!vendorSnapshot.hasData || + vendorSnapshot.connectionState == + ConnectionState.waiting) { return const SizedBox(); // Show placeholder or loader } VendorModel? vendorModel = vendorSnapshot.data; @@ -48,34 +66,78 @@ class AllCategoryProductScreen extends StatelessWidget { List selectedIndexVariants = []; List selectedIndexArray = []; if (productModel.itemAttribute != null) { - if (productModel.itemAttribute!.attributes!.isNotEmpty) { - for (var element in productModel.itemAttribute!.attributes!) { + if (productModel + .itemAttribute! + .attributes! + .isNotEmpty) { + for (var element + in productModel + .itemAttribute! + .attributes!) { if (element.attributeOptions!.isNotEmpty) { selectedVariants.add( - productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString(), + productModel + .itemAttribute! + .attributes![productModel + .itemAttribute! + .attributes! + .indexOf(element)] + .attributeOptions![0] + .toString(), ); selectedIndexVariants.add( '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', ); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedIndexArray.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { + if (productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .isNotEmpty) { price = Constant.productCommissionPrice( vendorModel!, - productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0', + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', ); disPrice = "0"; } } else { - price = Constant.productCommissionPrice(vendorModel!, productModel.price.toString()); - disPrice = double.parse(productModel.disPrice.toString()) <= 0 ? "0" : Constant.productCommissionPrice(vendorModel, productModel.disPrice.toString()); + price = Constant.productCommissionPrice( + vendorModel!, + productModel.price.toString(), + ); + disPrice = + double.parse( + productModel.disPrice.toString(), + ) <= + 0 + ? "0" + : Constant.productCommissionPrice( + vendorModel, + productModel.disPrice.toString(), + ); } return GestureDetector( onTap: () async { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -85,47 +147,108 @@ class AllCategoryProductScreen extends StatelessWidget { child: SizedBox( height: 90, width: Responsive.width(100, context), - child: NetworkImageWidget(imageUrl: productModel.photo.toString(), fit: BoxFit.cover), + child: NetworkImageWidget( + imageUrl: productModel.photo.toString(), + fit: BoxFit.cover, + ), ), ), Column( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( productModel.name!.capitalizeString(), textAlign: TextAlign.start, maxLines: 1, - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), disPrice == "" || disPrice == "0" - ? Text(Constant.amountShow(amount: price), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.primary300)) + ? Text( + Constant.amountShow(amount: price), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData.primary300, + ), + ) : Row( children: [ Text( - Constant.amountShow(amount: price), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: Colors.grey, decoration: TextDecoration.lineThrough), + Constant.amountShow( + amount: price, + ), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: Colors.grey, + decoration: + TextDecoration + .lineThrough, + ), ), const SizedBox(width: 5), Text( - Constant.amountShow(amount: disPrice), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: disPrice, + ), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.warning50 + : AppThemeData.warning50, + borderRadius: BorderRadius.circular( + 30, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.star, size: 18, color: AppThemeData.warning400), + Icon( + Icons.star, + size: 18, + color: AppThemeData.warning400, + ), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount.toString(), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsSum})", - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: AppThemeData.warning400), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + AppThemeData + .warning400, + ), ), ], ), diff --git a/lib/screen_ui/ecommarce/dash_board_e_commerce_screen.dart b/lib/screen_ui/ecommarce/dash_board_e_commerce_screen.dart index 9f7b0bd..dfdbdc0 100644 --- a/lib/screen_ui/ecommarce/dash_board_e_commerce_screen.dart +++ b/lib/screen_ui/ecommarce/dash_board_e_commerce_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../controllers/theme_controller.dart'; class DashBoardEcommerceScreen extends StatelessWidget { @@ -27,12 +26,19 @@ class DashBoardEcommerceScreen extends StatelessWidget { showUnselectedLabels: true, showSelectedLabels: true, selectedFontSize: 12, - selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), - unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), + selectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), + unselectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), currentIndex: controller.selectedIndex.value, - backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - selectedItemColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - unselectedItemColor: isDark ? AppThemeData.grey300 : AppThemeData.grey600, + backgroundColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + selectedItemColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, + unselectedItemColor: + isDark ? AppThemeData.grey300 : AppThemeData.grey600, onTap: (int index) { if (index == 0) { Get.put(DashBoardController()); @@ -42,17 +48,71 @@ class DashBoardEcommerceScreen extends StatelessWidget { items: Constant.walletSetting == false ? [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_orders.svg", label: 'Orders'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_orders.svg", + label: 'Orders'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ] : [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_wallet.svg", label: 'Wallet'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_orders.svg", label: 'Orders'.tr(), controller: controller), - navigationBarItem(isDark, index: 4, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_wallet.svg", + label: 'Wallet'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_orders.svg", + label: 'Orders'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 4, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ], ), ); @@ -61,7 +121,13 @@ class DashBoardEcommerceScreen extends StatelessWidget { }); } - BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required DashBoardEcommerceController controller}) { + BottomNavigationBarItem navigationBarItem( + isDark, { + required int index, + required String label, + required String assetIcon, + required DashBoardEcommerceController controller, + }) { return BottomNavigationBarItem( icon: Padding( padding: const EdgeInsets.symmetric(vertical: 5), diff --git a/lib/screen_ui/ecommarce/home_e_commerce_screen.dart b/lib/screen_ui/ecommarce/home_e_commerce_screen.dart index cae6b77..7e4dae3 100644 --- a/lib/screen_ui/ecommarce/home_e_commerce_screen.dart +++ b/lib/screen_ui/ecommarce/home_e_commerce_screen.dart @@ -17,7 +17,8 @@ import 'package:customer/screen_ui/location_enable_screens/address_list_screen.d import 'package:customer/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart'; -import 'package:customer/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart' show RestaurantListScreen; +import 'package:customer/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart' + show RestaurantListScreen; import 'package:customer/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart'; import 'package:customer/screen_ui/multi_vendor_service/search_screen/search_screen.dart'; @@ -37,7 +38,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:url_launcher/url_launcher.dart'; class HomeECommerceScreen extends StatelessWidget { @@ -53,13 +54,18 @@ class HomeECommerceScreen extends StatelessWidget { return Scaffold( backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, + backgroundColor: + isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, titleSpacing: 0, leading: InkWell( onTap: () { Get.back(); }, - child: Icon(Icons.arrow_back, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, size: 20), + child: Icon( + Icons.arrow_back, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, + size: 20, + ), ), title: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -69,9 +75,27 @@ class HomeECommerceScreen extends StatelessWidget { onTap: () { Get.offAll(const LoginScreen()); }, - child: Text("Login".tr(), textAlign: TextAlign.center, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 12)), + child: Text( + "Login".tr(), + textAlign: TextAlign.center, + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontSize: 12, + ), + ), ) - : Text(Constant.userModel!.fullName(), textAlign: TextAlign.center, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 12)), + : Text( + Constant.userModel!.fullName(), + textAlign: TextAlign.center, + style: AppThemeData.semiBoldTextStyle( + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey50, + fontSize: 12, + ), + ), InkWell( onTap: () async { if (Constant.userModel != null) { @@ -96,7 +120,9 @@ class HomeECommerceScreen extends StatelessWidget { ShowToastDialog.closeLoader(); if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; final lat = firstPlace.coordinates.latitude; @@ -105,19 +131,31 @@ class HomeECommerceScreen extends StatelessWidget { shippingAddress.addressAs = "Home"; shippingAddress.locality = address.toString(); - shippingAddress.location = UserLocation(latitude: lat, longitude: lng); + shippingAddress.location = UserLocation( + latitude: lat, + longitude: lng, + ); Constant.selectedLocation = shippingAddress; controller.getData(); Get.back(); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel selectedLocationModel = + value; shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); - shippingAddress.locality = "Picked from Map"; // You can reverse-geocode + shippingAddress.location = UserLocation( + latitude: + selectedLocationModel.latLng!.latitude, + longitude: + selectedLocationModel.latLng!.longitude, + ); + shippingAddress.locality = + "Picked from Map"; // You can reverse-geocode Constant.selectedLocation = shippingAddress; controller.getData(); @@ -125,9 +163,15 @@ class HomeECommerceScreen extends StatelessWidget { }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; - shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + shippingAddress.location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; shippingAddress.locality = currentLocation; @@ -147,8 +191,25 @@ class HomeECommerceScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, TextSpan( children: [ - TextSpan(text: Constant.selectedLocation.getFullAddress(), style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 14)), - WidgetSpan(child: SvgPicture.asset("assets/icons/ic_down.svg", colorFilter: ColorFilter.mode(AppThemeData.grey50, BlendMode.srcIn))), + TextSpan( + text: Constant.selectedLocation.getFullAddress(), + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontSize: 14, + ), + ), + WidgetSpan( + child: SvgPicture.asset( + "assets/icons/ic_down.svg", + colorFilter: ColorFilter.mode( + AppThemeData.grey50, + BlendMode.srcIn, + ), + ), + ), ], ), ), @@ -168,10 +229,14 @@ class HomeECommerceScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey50, ), ), - badgeStyle: badges.BadgeStyle(shape: badges.BadgeShape.circle, badgeColor: AppThemeData.info300), + badgeStyle: badges.BadgeStyle( + shape: badges.BadgeShape.circle, + badgeColor: AppThemeData.info300, + ), child: InkWell( onTap: () async { (await Get.to(const CartScreen())); @@ -182,11 +247,28 @@ class HomeECommerceScreen extends StatelessWidget { width: 30, height: 30, decoration: ShapeDecoration( - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), borderRadius: BorderRadius.circular(120)), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + borderRadius: BorderRadius.circular(120), + ), ), child: Padding( padding: const EdgeInsets.all(8.0), - child: SvgPicture.asset("assets/icons/ic_shoping_cart.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey50 : AppThemeData.grey50, BlendMode.srcIn)), + child: SvgPicture.asset( + "assets/icons/ic_shoping_cart.svg", + colorFilter: ColorFilter.mode( + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + BlendMode.srcIn, + ), + ), ), ), ), @@ -196,22 +278,39 @@ class HomeECommerceScreen extends StatelessWidget { ), ], bottom: PreferredSize( - preferredSize: Size.fromHeight(50.0), // height of the bottom widget + preferredSize: Size.fromHeight( + 50.0, + ), // height of the bottom widget child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), child: InkWell( onTap: () { - Get.to(const SearchScreen(), arguments: {"vendorList": controller.allNearestRestaurant}); + Get.to( + const SearchScreen(), + arguments: { + "vendorList": controller.allNearestRestaurant, + }, + ); }, child: TextFieldWidget( hintText: 'Search the store, item and more...'.tr(), controller: null, enable: false, backgroundColor: AppThemeData.grey50, - hintColor: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + hintColor: + isDark ? AppThemeData.grey400 : AppThemeData.grey400, prefix: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), - child: SvgPicture.asset("assets/icons/ic_search.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey400 : AppThemeData.grey400, BlendMode.srcIn)), + child: SvgPicture.asset( + "assets/icons/ic_search.svg", + colorFilter: ColorFilter.mode( + isDark ? AppThemeData.grey400 : AppThemeData.grey400, + BlendMode.srcIn, + ), + ), ), ), ), @@ -236,7 +335,13 @@ class HomeECommerceScreen extends StatelessWidget { child: Text( "Category".tr(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), ), ), InkWell( @@ -248,7 +353,10 @@ class HomeECommerceScreen extends StatelessWidget { textAlign: TextAlign.start, style: AppThemeData.semiBoldTextStyle( decoration: TextDecoration.underline, - color: isDark ? AppThemeData.multiVendorDark300 : AppThemeData.multiVendor300, + color: + isDark + ? AppThemeData.multiVendorDark300 + : AppThemeData.multiVendor300, fontSize: 14, ), ), @@ -264,26 +372,51 @@ class HomeECommerceScreen extends StatelessWidget { child: ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemCount: controller.vendorCategoryModel.length, + itemCount: + controller.vendorCategoryModel.length, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { - VendorCategoryModel vendorCategoryModel = controller.vendorCategoryModel[index]; + VendorCategoryModel vendorCategoryModel = + controller.vendorCategoryModel[index]; return InkWell( onTap: () { - Get.to(const CategoryRestaurantScreen(), arguments: {"vendorCategoryModel": vendorCategoryModel, "dineIn": false}); + Get.to( + const CategoryRestaurantScreen(), + arguments: { + "vendorCategoryModel": + vendorCategoryModel, + "dineIn": false, + }, + ); }, child: Padding( padding: const EdgeInsets.only(right: 18), child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - NetworkImageWidget(imageUrl: vendorCategoryModel.photo.toString(), height: 60, width: 60, fit: BoxFit.cover), + NetworkImageWidget( + imageUrl: + vendorCategoryModel.photo + .toString(), + height: 60, + width: 60, + fit: BoxFit.cover, + ), const SizedBox(height: 5), Text( - vendorCategoryModel.title.toString(), + vendorCategoryModel.title + .toString(), textAlign: TextAlign.center, - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, fontSize: 14), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + fontSize: 14, + ), ), ], ), @@ -294,20 +427,38 @@ class HomeECommerceScreen extends StatelessWidget { ), ), SizedBox(height: 10), - Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: controller.bannerModel.isEmpty ? const SizedBox() : BannerView(controller: controller)), - Visibility(visible: (Constant.isEnableAdsFeature == true && controller.advertisementList.isNotEmpty), child: const SizedBox(height: 20)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: + controller.bannerModel.isEmpty + ? const SizedBox() + : BannerView(controller: controller), + ), + Visibility( + visible: + (Constant.isEnableAdsFeature == true && + controller.advertisementList.isNotEmpty), + child: const SizedBox(height: 20), + ), Visibility( visible: Constant.isEnableAdsFeature == true, child: controller.advertisementList.isEmpty ? const SizedBox() : Container( - color: AppThemeData.primary300.withAlpha(40), + color: AppThemeData.primary300.withAlpha( + 40, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ @@ -315,19 +466,41 @@ class HomeECommerceScreen extends StatelessWidget { child: Text( "Highlights for you".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + ), ), ), InkWell( onTap: () { - Get.to(AllAdvertisementScreen())?.then((value) { - controller.getFavouriteRestaurant(); + Get.to( + AllAdvertisementScreen(), + )?.then((value) { + controller + .getFavouriteRestaurant(); }); }, child: Text( "View all".tr(), textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ], @@ -336,12 +509,30 @@ class HomeECommerceScreen extends StatelessWidget { SizedBox( height: 220, child: ListView.builder( - physics: const BouncingScrollPhysics(), - scrollDirection: Axis.horizontal, - itemCount: controller.advertisementList.length >= 10 ? 10 : controller.advertisementList.length, + physics: + const BouncingScrollPhysics(), + scrollDirection: + Axis.horizontal, + itemCount: + controller + .advertisementList + .length >= + 10 + ? 10 + : controller + .advertisementList + .length, padding: EdgeInsets.all(0), - itemBuilder: (BuildContext context, int index) { - return AdvertisementHomeCard(controller: controller, model: controller.advertisementList[index]); + itemBuilder: ( + BuildContext context, + int index, + ) { + return AdvertisementHomeCard( + controller: controller, + model: + controller + .advertisementList[index], + ); }, ), ), @@ -356,7 +547,13 @@ class HomeECommerceScreen extends StatelessWidget { child: Text( "New Arrivals".tr(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), ), ), SizedBox(height: 20), @@ -372,7 +569,13 @@ class HomeECommerceScreen extends StatelessWidget { childAspectRatio: 1 / 1.1, padding: EdgeInsets.zero, physics: NeverScrollableScrollPhysics(), - children: controller.newArrivalRestaurantList.take(4).map((item) => NewArrivalCard(item: item)).toList(), + children: + controller.newArrivalRestaurantList + .take(4) + .map( + (item) => NewArrivalCard(item: item), + ) + .toList(), ), ), ), @@ -381,11 +584,24 @@ class HomeECommerceScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: RoundedButtonBorder( radius: 10, - color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + color: + isDark + ? AppThemeData.greyDark100 + : AppThemeData.grey100, + borderColor: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, title: 'View All Arrivals'.tr(), onPress: () { - Get.to(RestaurantListScreen(), arguments: {"vendorList": controller.newArrivalRestaurantList, "title": "New Arrivals".tr()}); + Get.to( + RestaurantListScreen(), + arguments: { + "vendorList": + controller.newArrivalRestaurantList, + "title": "New Arrivals".tr(), + }, + ); }, ), ), @@ -395,19 +611,38 @@ class HomeECommerceScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Top Brands".tr(), textAlign: TextAlign.start, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)), + Text( + "Top Brands".tr(), + textAlign: TextAlign.start, + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), SizedBox(height: 10), GridView.builder( padding: EdgeInsets.zero, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 4.5 / 6, crossAxisSpacing: 2), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + childAspectRatio: 4.5 / 6, + crossAxisSpacing: 2, + ), itemCount: controller.brandList.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { - BrandsModel brandModel = controller.brandList[index]; + BrandsModel brandModel = + controller.brandList[index]; return InkWell( onTap: () { - Get.to(AllBrandProductScreen(), arguments: {"brandModel": brandModel}); + Get.to( + AllBrandProductScreen(), + arguments: {"brandModel": brandModel}, + ); }, child: Column( children: [ @@ -415,20 +650,49 @@ class HomeECommerceScreen extends StatelessWidget { width: 80, height: 80, decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, strokeAlign: BorderSide.strokeAlignOutside, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100), - borderRadius: BorderRadius.circular(10), + side: BorderSide( + width: 1, + strokeAlign: + BorderSide + .strokeAlignOutside, + color: + isDark + ? AppThemeData.grey800 + : AppThemeData + .grey100, + ), + borderRadius: + BorderRadius.circular(10), + ), + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: ClipOval( + child: NetworkImageWidget( + imageUrl: + brandModel.photo + .toString(), + fit: BoxFit.cover, + ), ), ), - child: Padding(padding: const EdgeInsets.all(10), child: ClipOval(child: NetworkImageWidget(imageUrl: brandModel.photo.toString(), fit: BoxFit.cover))), ), SizedBox(height: 5), Text( '${brandModel.title}', textAlign: TextAlign.center, maxLines: 2, - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), @@ -443,137 +707,389 @@ class HomeECommerceScreen extends StatelessWidget { shrinkWrap: true, physics: const BouncingScrollPhysics(), padding: EdgeInsets.zero, - itemCount: controller.categoryWiseProductList.length, + itemCount: + controller.categoryWiseProductList.length, itemBuilder: (context, index) { - VendorCategoryModel item = controller.categoryWiseProductList[index]; - String imagePath = ["assets/images/ic_product_bg_1.png", "assets/images/ic_product_bg_2.png", "assets/images/ic_product_bg_3.png"][index % ["", "", ""].length]; + VendorCategoryModel item = + controller.categoryWiseProductList[index]; + String imagePath = + [ + "assets/images/ic_product_bg_1.png", + "assets/images/ic_product_bg_2.png", + "assets/images/ic_product_bg_3.png", + ][index % ["", "", ""].length]; return Container( width: Responsive.width(100, context), - decoration: BoxDecoration(image: DecorationImage(image: AssetImage(imagePath), fit: BoxFit.fill)), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(imagePath), + fit: BoxFit.fill, + ), + ), child: Padding( - padding: const EdgeInsets.only(left: 16, right: 16, top: 10, bottom: 20), + padding: const EdgeInsets.only( + left: 16, + right: 16, + top: 10, + bottom: 20, + ), child: FutureBuilder>( - future: FireStoreUtils.getProductListByCategoryId(item.id.toString()), + future: + FireStoreUtils.getProductListByCategoryId( + item.id.toString(), + ), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))); - } else if ((snapshot.hasData || (snapshot.data?.isNotEmpty ?? false))) { - List productList = snapshot.data!; + if (snapshot.connectionState == + ConnectionState.waiting) { + return Center( + child: + CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData.primary300, + ), + ), + ); + } else if ((snapshot.hasData || + (snapshot.data?.isNotEmpty ?? + false))) { + List productList = + snapshot.data!; return snapshot.data!.isEmpty ? Container() : Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, children: [ - Text(item.title.toString(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(color: AppThemeData.grey900, fontSize: 18)), Text( - "Style up with the latest fits, now at unbeatable prices.".tr(), + item.title.toString(), textAlign: TextAlign.start, - style: AppThemeData.regularTextStyle(color: AppThemeData.grey900, fontSize: 12), + style: + AppThemeData.boldTextStyle( + color: + AppThemeData + .grey900, + fontSize: 18, + ), + ), + Text( + "Style up with the latest fits, now at unbeatable prices." + .tr(), + textAlign: TextAlign.start, + style: + AppThemeData.regularTextStyle( + color: + AppThemeData + .grey900, + fontSize: 12, + ), ), SizedBox(height: 20), GridView.builder( shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 3.5 / 6, crossAxisSpacing: 10), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + childAspectRatio: + 3.5 / 6, + crossAxisSpacing: 10, + ), padding: EdgeInsets.zero, - physics: NeverScrollableScrollPhysics(), - itemCount: productList.length > 6 ? 6 : productList.length, - itemBuilder: (context, index) { - ProductModel productModel = productList[index]; + physics: + NeverScrollableScrollPhysics(), + itemCount: + productList.length > 6 + ? 6 + : productList.length, + itemBuilder: ( + context, + index, + ) { + ProductModel productModel = + productList[index]; return FutureBuilder( - future: FireStoreUtils.getVendorById(productModel.vendorID.toString()), - builder: (context, vendorSnapshot) { - if (!vendorSnapshot.hasData || vendorSnapshot.connectionState == ConnectionState.waiting) { + future: + FireStoreUtils.getVendorById( + productModel + .vendorID + .toString(), + ), + builder: ( + context, + vendorSnapshot, + ) { + if (!vendorSnapshot + .hasData || + vendorSnapshot + .connectionState == + ConnectionState + .waiting) { return const SizedBox(); // Show placeholder or loader } - VendorModel? vendorModel = vendorSnapshot.data; + VendorModel? + vendorModel = + vendorSnapshot.data; String price = "0.0"; String disPrice = "0.0"; - List selectedVariants = []; - List selectedIndexVariants = []; - List selectedIndexArray = []; - if (productModel.itemAttribute != null) { - if (productModel.itemAttribute!.attributes!.isNotEmpty) { - for (var element in productModel.itemAttribute!.attributes!) { - if (element.attributeOptions!.isNotEmpty) { + List + selectedVariants = []; + List + selectedIndexVariants = + []; + List + selectedIndexArray = []; + if (productModel + .itemAttribute != + null) { + if (productModel + .itemAttribute! + .attributes! + .isNotEmpty) { + for (var element + in productModel + .itemAttribute! + .attributes!) { + if (element + .attributeOptions! + .isNotEmpty) { selectedVariants.add( - productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString(), + productModel + .itemAttribute! + .attributes![productModel + .itemAttribute! + .attributes! + .indexOf( + element, + )] + .attributeOptions![0] + .toString(), ); - selectedIndexVariants.add( - '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', - ); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedIndexVariants + .add( + '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', + ); + selectedIndexArray + .add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { + if (productModel + .itemAttribute! + .variants! + .where( + (element) => + element + .variantSku == + selectedVariants + .join( + '-', + ), + ) + .isNotEmpty) { price = Constant.productCommissionPrice( vendorModel!, - productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0', + productModel + .itemAttribute! + .variants! + .where( + ( + element, + ) => + element.variantSku == + selectedVariants.join( + '-', + ), + ) + .first + .variantPrice ?? + '0', ); disPrice = "0"; } } else { - price = Constant.productCommissionPrice(vendorModel!, productModel.price.toString()); + price = + Constant.productCommissionPrice( + vendorModel!, + productModel + .price + .toString(), + ); disPrice = - double.parse(productModel.disPrice.toString()) <= 0 + double.parse( + productModel + .disPrice + .toString(), + ) <= + 0 ? "0" - : Constant.productCommissionPrice(vendorModel, productModel.disPrice.toString()); + : Constant.productCommissionPrice( + vendorModel, + productModel + .disPrice + .toString(), + ); } return GestureDetector( onTap: () async { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: { + "vendorModel": + vendorModel, + }, + ); }, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ ClipRRect( - borderRadius: BorderRadius.circular(10), + borderRadius: + BorderRadius.circular( + 10, + ), child: SizedBox( height: 90, - width: Responsive.width(100, context), - child: NetworkImageWidget(imageUrl: productModel.photo.toString(), fit: BoxFit.cover), + width: + Responsive.width( + 100, + context, + ), + child: NetworkImageWidget( + imageUrl: + productModel + .photo + .toString(), + fit: + BoxFit + .cover, + ), ), ), Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - productModel.name!.capitalizeString(), - textAlign: TextAlign.start, + productModel + .name! + .capitalizeString(), + textAlign: + TextAlign + .start, maxLines: 1, - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.semiBoldTextStyle( + fontSize: + 18, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), - disPrice == "" || disPrice == "0" - ? Text(Constant.amountShow(amount: price), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.primary300)) + disPrice == + "" || + disPrice == + "0" + ? Text( + Constant.amountShow( + amount: + price, + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: + 16, + color: + AppThemeData.primary300, + ), + ) : Column( children: [ Text( - Constant.amountShow(amount: price), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: Colors.grey, decoration: TextDecoration.lineThrough), + Constant.amountShow( + amount: + price, + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: + 14, + color: + Colors.grey, + decoration: + TextDecoration.lineThrough, + ), + ), + const SizedBox( + width: + 5, ), - const SizedBox(width: 5), Text( - Constant.amountShow(amount: disPrice), - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + disPrice, + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: + 14, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.warning50 + : AppThemeData.warning50, + borderRadius: + BorderRadius.circular( + 30, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: + 10, + vertical: + 6, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisSize: + MainAxisSize.min, children: [ - Icon(Icons.star, size: 18, color: AppThemeData.warning400), + Icon( + Icons.star, + size: + 18, + color: + AppThemeData.warning400, + ), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount.toString(), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsSum})", - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: AppThemeData.warning400), + style: AppThemeData.semiBoldTextStyle( + fontSize: + 12, + color: + AppThemeData.warning400, + ), ), ], ), @@ -590,11 +1106,26 @@ class HomeECommerceScreen extends StatelessWidget { ), RoundedButtonBorder( radius: 10, - color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + color: + isDark + ? AppThemeData + .greyDark100 + : AppThemeData + .grey100, + borderColor: + isDark + ? AppThemeData + .greyDark200 + : AppThemeData + .grey200, title: 'View All Products', onPress: () { - Get.to(AllCategoryProductScreen(), arguments: {"categoryModel": item}); + Get.to( + AllCategoryProductScreen(), + arguments: { + "categoryModel": item, + }, + ); }, ), ], @@ -609,7 +1140,13 @@ class HomeECommerceScreen extends StatelessWidget { }, ), SizedBox(height: 10), - Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: controller.bannerModel.isEmpty ? const SizedBox() : BannerBottomView(controller: controller)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: + controller.bannerModel.isEmpty + ? const SizedBox() + : BannerBottomView(controller: controller), + ), // Visibility( // visible: (Constant.isEnableAdsFeature == true && controller.advertisementList.isNotEmpty), // child: const SizedBox(height: 20), @@ -687,56 +1224,145 @@ class HomeECommerceScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("All Store".tr(), textAlign: TextAlign.start, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)), + Text( + "All Store".tr(), + textAlign: TextAlign.start, + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), SizedBox(height: 10), ListView.builder( padding: EdgeInsets.zero, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemCount: controller.allNearestRestaurant.length > 8 ? 8 : controller.allNearestRestaurant.length, + itemCount: + controller.allNearestRestaurant.length > 8 + ? 8 + : controller + .allNearestRestaurant + .length, itemBuilder: (context, index) { - VendorModel item = controller.allNearestRestaurant[index]; + VendorModel item = + controller.allNearestRestaurant[index]; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": item}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": item}, + ); }, child: Padding( - padding: const EdgeInsets.only(bottom: 20), + padding: const EdgeInsets.only( + bottom: 20, + ), child: Row( children: [ - ClipRRect(borderRadius: BorderRadius.circular(10), child: NetworkImageWidget(imageUrl: item.photo.toString(), height: 80, width: 130, fit: BoxFit.cover)), + ClipRRect( + borderRadius: + BorderRadius.circular(10), + child: NetworkImageWidget( + imageUrl: item.photo.toString(), + height: 80, + width: 130, + fit: BoxFit.cover, + ), + ), SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text(item.title.toString(), style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)), + Text( + item.title.toString(), + style: + AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + fontSize: 16, + ), + ), Row( children: [ - Icon(Icons.location_on, size: 14, color: Colors.grey), + Icon( + Icons.location_on, + size: 14, + color: Colors.grey, + ), SizedBox(width: 4), Expanded( child: Text( - item.location.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), - overflow: TextOverflow.ellipsis, + item.location + .toString(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData + .greyDark500 + : AppThemeData + .grey500, + ), + overflow: + TextOverflow + .ellipsis, ), ), ], ), Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData + .warning50 + : AppThemeData + .warning50, + borderRadius: + BorderRadius.circular( + 30, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + mainAxisSize: + MainAxisSize.min, children: [ - Icon(Icons.star, size: 18, color: AppThemeData.warning400), + Icon( + Icons.star, + size: 18, + color: + AppThemeData + .warning400, + ), Text( "${Constant.calculateReview(reviewCount: item.reviewsCount.toString(), reviewSum: item.reviewsSum.toString())} (${item.reviewsSum})", - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: AppThemeData.warning400), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + AppThemeData + .warning400, + ), ), ], ), @@ -753,11 +1379,23 @@ class HomeECommerceScreen extends StatelessWidget { ), RoundedButtonBorder( radius: 10, - color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + color: + isDark + ? AppThemeData.greyDark100 + : AppThemeData.grey100, + borderColor: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, title: 'View All Stores'.tr(), onPress: () { - Get.to(const RestaurantListScreen(), arguments: {"vendorList": controller.allNearestRestaurant}); + Get.to( + const RestaurantListScreen(), + arguments: { + "vendorList": + controller.allNearestRestaurant, + }, + ); }, ), ], @@ -784,7 +1422,10 @@ class NewArrivalCard extends StatelessWidget { final isDark = themeController.isDark.value; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": item}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": item}, + ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -795,11 +1436,20 @@ class NewArrivalCard extends StatelessWidget { height: 100, width: double.infinity, fit: BoxFit.cover, - imageUrl: item.photo != null && item.photo!.isNotEmpty ? item.photo.toString() : Constant.placeHolderImage.toString(), + imageUrl: + item.photo != null && item.photo!.isNotEmpty + ? item.photo.toString() + : Constant.placeHolderImage.toString(), ), ), SizedBox(height: 5), - Text(item.title.toString(), style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 14)), + Text( + item.title.toString(), + style: AppThemeData.semiBoldTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + fontSize: 14, + ), + ), Row( children: [ Icon(Icons.location_on, size: 14, color: Colors.grey), @@ -807,14 +1457,23 @@ class NewArrivalCard extends StatelessWidget { Expanded( child: Text( item.location.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), overflow: TextOverflow.ellipsis, ), ), ], ), Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, borderRadius: BorderRadius.circular(30)), + decoration: BoxDecoration( + color: isDark ? AppThemeData.warning50 : AppThemeData.warning50, + borderRadius: BorderRadius.circular(30), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), child: Row( @@ -825,7 +1484,10 @@ class NewArrivalCard extends StatelessWidget { Icon(Icons.star, size: 18, color: AppThemeData.warning400), Text( "${Constant.calculateReview(reviewCount: item.reviewsCount.toString(), reviewSum: item.reviewsSum.toString())} (${item.reviewsSum})", - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: AppThemeData.warning400), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: AppThemeData.warning400, + ), ), ], ), @@ -865,17 +1527,32 @@ class BannerView extends StatelessWidget { onTap: () async { if (bannerModel.redirect_type == "store") { ShowToastDialog.showLoader("Please wait...".tr()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(bannerModel.redirect_id.toString()); + VendorModel? vendorModel = + await FireStoreUtils.getVendorById( + bannerModel.redirect_id.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "product") { ShowToastDialog.showLoader("Please wait...".tr()); - ProductModel? productModel = await FireStoreUtils.getProductById(bannerModel.redirect_id.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(productModel!.vendorID.toString()); + ProductModel? productModel = + await FireStoreUtils.getProductById( + bannerModel.redirect_id.toString(), + ); + VendorModel? vendorModel = + await FireStoreUtils.getVendorById( + productModel!.vendorID.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "external_link") { final uri = Uri.parse(bannerModel.redirect_id.toString()); if (await canLaunchUrl(uri)) { @@ -887,7 +1564,13 @@ class BannerView extends StatelessWidget { }, child: Padding( padding: const EdgeInsets.only(right: 14), - child: ClipRRect(borderRadius: const BorderRadius.all(Radius.circular(12)), child: NetworkImageWidget(imageUrl: bannerModel.photo.toString(), fit: BoxFit.cover)), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: NetworkImageWidget( + imageUrl: bannerModel.photo.toString(), + fit: BoxFit.cover, + ), + ), ), ); }, @@ -905,7 +1588,13 @@ class BannerView extends StatelessWidget { alignment: Alignment.centerLeft, height: 9, width: 9, - decoration: BoxDecoration(shape: BoxShape.circle, color: controller.currentPage.value == index ? AppThemeData.primary300 : Colors.black12), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + controller.currentPage.value == index + ? AppThemeData.primary300 + : Colors.black12, + ), ), ); }), @@ -944,17 +1633,32 @@ class BannerBottomView extends StatelessWidget { onTap: () async { if (bannerModel.redirect_type == "store") { ShowToastDialog.showLoader("Please wait...".tr()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(bannerModel.redirect_id.toString()); + VendorModel? vendorModel = + await FireStoreUtils.getVendorById( + bannerModel.redirect_id.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "product") { ShowToastDialog.showLoader("Please wait...".tr()); - ProductModel? productModel = await FireStoreUtils.getProductById(bannerModel.redirect_id.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(productModel!.vendorID.toString()); + ProductModel? productModel = + await FireStoreUtils.getProductById( + bannerModel.redirect_id.toString(), + ); + VendorModel? vendorModel = + await FireStoreUtils.getVendorById( + productModel!.vendorID.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "external_link") { final uri = Uri.parse(bannerModel.redirect_id.toString()); if (await canLaunchUrl(uri)) { @@ -966,7 +1670,13 @@ class BannerBottomView extends StatelessWidget { }, child: Padding( padding: const EdgeInsets.only(right: 14), - child: ClipRRect(borderRadius: const BorderRadius.all(Radius.circular(12)), child: NetworkImageWidget(imageUrl: bannerModel.photo.toString(), fit: BoxFit.cover)), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: NetworkImageWidget( + imageUrl: bannerModel.photo.toString(), + fit: BoxFit.cover, + ), + ), ), ); }, @@ -977,14 +1687,22 @@ class BannerBottomView extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, - children: List.generate(controller.bannerBottomModel.length, (index) { + children: List.generate(controller.bannerBottomModel.length, ( + index, + ) { return Obx( () => Container( margin: const EdgeInsets.only(right: 5), alignment: Alignment.centerLeft, height: 9, width: 9, - decoration: BoxDecoration(shape: BoxShape.circle, color: controller.currentBottomPage.value == index ? AppThemeData.primary300 : Colors.black12), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + controller.currentBottomPage.value == index + ? AppThemeData.primary300 + : Colors.black12, + ), ), ); }), @@ -999,7 +1717,11 @@ class AdvertisementHomeCard extends StatelessWidget { final AdvertisementModel model; final HomeECommerceController controller; - const AdvertisementHomeCard({super.key, required this.controller, required this.model}); + const AdvertisementHomeCard({ + super.key, + required this.controller, + required this.model, + }); @override Widget build(BuildContext context) { @@ -1008,9 +1730,14 @@ class AdvertisementHomeCard extends StatelessWidget { return InkWell( onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(model.vendorId!); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + model.vendorId!, + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Container( margin: EdgeInsets.only(right: 16), @@ -1018,7 +1745,14 @@ class AdvertisementHomeCard extends StatelessWidget { decoration: BoxDecoration( color: isDark ? AppThemeData.info600 : AppThemeData.surface, borderRadius: BorderRadius.circular(16), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: isDark ? 6 : 2, spreadRadius: 0, offset: Offset(0, isDark ? 3 : 1))], + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: isDark ? 6 : 2, + spreadRadius: 0, + offset: Offset(0, isDark ? 3 : 1), + ), + ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1027,18 +1761,32 @@ class AdvertisementHomeCard extends StatelessWidget { children: [ model.type == 'restaurant_promotion' ? ClipRRect( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - child: NetworkImageWidget(imageUrl: model.coverImage ?? '', height: 135, width: double.infinity, fit: BoxFit.cover), + borderRadius: BorderRadius.vertical( + top: Radius.circular(16), + ), + child: NetworkImageWidget( + imageUrl: model.coverImage ?? '', + height: 135, + width: double.infinity, + fit: BoxFit.cover, + ), ) - : VideoAdvWidget(url: model.video ?? '', height: 135, width: double.infinity), - if (model.type != 'video_promotion' && model.vendorId != null && (model.showRating == true || model.showReview == true)) + : VideoAdvWidget( + url: model.video ?? '', + height: 135, + width: double.infinity, + ), + if (model.type != 'video_promotion' && + model.vendorId != null && + (model.showRating == true || model.showReview == true)) Positioned( bottom: 8, right: 8, child: FutureBuilder( future: FireStoreUtils.getVendorById(model.vendorId!), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot.connectionState == + ConnectionState.waiting) { return const SizedBox(); } else { if (snapshot.hasError) { @@ -1048,16 +1796,43 @@ class AdvertisementHomeCard extends StatelessWidget { } else { VendorModel vendorModel = snapshot.data!; return Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(120), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), child: Row( children: [ - if (model.showRating == true) SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), - if (model.showRating == true) const SizedBox(width: 5), + if (model.showRating == true) + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), + if (model.showRating == true) + const SizedBox(width: 5), Text( "${model.showRating == true ? Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString()) : ''} ${model.showReview == true ? '(${vendorModel.reviewsCount!.toStringAsFixed(0)})' : ''}", - style: TextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ], ), @@ -1076,7 +1851,15 @@ class AdvertisementHomeCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ if (model.type == 'restaurant_promotion') - ClipRRect(borderRadius: BorderRadius.circular(30), child: NetworkImageWidget(imageUrl: model.profileImage ?? '', height: 50, width: 50, fit: BoxFit.cover)), + ClipRRect( + borderRadius: BorderRadius.circular(30), + child: NetworkImageWidget( + imageUrl: model.profileImage ?? '', + height: 50, + width: 50, + fit: BoxFit.cover, + ), + ), SizedBox(width: 8), Expanded( child: Column( @@ -1084,12 +1867,26 @@ class AdvertisementHomeCard extends StatelessWidget { children: [ Text( model.title ?? '', - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 14, fontWeight: FontWeight.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 14, + fontWeight: FontWeight.bold, + ), overflow: TextOverflow.ellipsis, ), Text( model.description ?? '', - style: TextStyle(fontSize: 12, fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey400 : AppThemeData.grey600), + style: TextStyle( + fontSize: 12, + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey600, + ), overflow: TextOverflow.ellipsis, maxLines: 2, ), @@ -1100,26 +1897,73 @@ class AdvertisementHomeCard extends StatelessWidget { ? IconButton( icon: Obx( () => - controller.favouriteList.where((p0) => p0.restaurantId == model.vendorId).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey400 : AppThemeData.grey600, BlendMode.srcIn)), + controller.favouriteList + .where( + (p0) => + p0.restaurantId == model.vendorId, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + colorFilter: ColorFilter.mode( + isDark + ? AppThemeData.grey400 + : AppThemeData.grey600, + BlendMode.srcIn, + ), + ), ), onPressed: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == model.vendorId).isNotEmpty) { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: model.vendorId, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.removeWhere((item) => item.restaurantId == model.vendorId); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); + if (controller.favouriteList + .where((p0) => p0.restaurantId == model.vendorId) + .isNotEmpty) { + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: model.vendorId, + userId: FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.removeWhere( + (item) => item.restaurantId == model.vendorId, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: model.vendorId, userId: FireStoreUtils.getCurrentUid()); + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: model.vendorId, + userId: FireStoreUtils.getCurrentUid(), + ); controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } controller.update(); }, ) : Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))), - child: Padding(padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), child: Icon(Icons.arrow_forward, size: 20, color: AppThemeData.primary300)), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + child: Icon( + Icons.arrow_forward, + size: 20, + color: AppThemeData.primary300, + ), + ), ), ], ), diff --git a/lib/screen_ui/location_enable_screens/address_list_screen.dart b/lib/screen_ui/location_enable_screens/address_list_screen.dart index 474620a..f8eca2e 100644 --- a/lib/screen_ui/location_enable_screens/address_list_screen.dart +++ b/lib/screen_ui/location_enable_screens/address_list_screen.dart @@ -10,7 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class AddressListScreen extends StatelessWidget { const AddressListScreen({super.key}); @@ -39,50 +39,120 @@ class AddressListScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("My Addresses".tr(), style: AppThemeData.boldTextStyle(fontSize: 24, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "My Addresses".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 5), - Text("Allows users to view, manage, add, or edit delivery addresses.".tr(), style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.grey600)), + Text( + "Allows users to view, manage, add, or edit delivery addresses." + .tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.grey600, + ), + ), const SizedBox(height: 24), Expanded( child: controller.shippingAddressList.isEmpty - ? Constant.showEmptyView(message: "Address not found".tr()) + ? Constant.showEmptyView( + message: "Address not found".tr(), + ) : ListView.separated( - itemCount: controller.shippingAddressList.length, + itemCount: + controller.shippingAddressList.length, itemBuilder: (context, index) { - ShippingAddress address = controller.shippingAddressList[index]; + ShippingAddress address = + controller.shippingAddressList[index]; return InkWell( onTap: () { Get.back(result: address); }, child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, borderRadius: BorderRadius.circular(8)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData + .greyDark100 + : AppThemeData + .grey100, + borderRadius: + BorderRadius.circular( + 8, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Text( - address.addressAs.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + address.addressAs + .toString(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ), ), SizedBox(width: 10), address.isDefault == true ? Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.success100 : AppThemeData.success100, borderRadius: BorderRadius.circular(8)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData + .success100 + : AppThemeData + .success100, + borderRadius: + BorderRadius.circular( + 8, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: + const EdgeInsets.symmetric( + horizontal: + 10, + vertical: 5, + ), child: Text( "Default".tr(), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ), ) @@ -91,35 +161,72 @@ class AddressListScreen extends StatelessWidget { ), SizedBox(height: 10), Text( - address.getFullAddress().toString(), - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800), + address + .getFullAddress() + .toString(), + style: + AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark800 + : AppThemeData + .grey800, + ), ), ], ), ), InkWell( onTap: () async { - await controller.deleteAddress(index); + await controller.deleteAddress( + index, + ); }, - child: SvgPicture.asset("assets/icons/ic_delete_address.svg"), + child: SvgPicture.asset( + "assets/icons/ic_delete_address.svg", + ), ), SizedBox(width: 10), InkWell( onTap: () { - Get.to(EnterManuallyLocationScreen(), arguments: {"address": address, "mode": "Edit"})!.then((value) { + Get.to( + EnterManuallyLocationScreen(), + arguments: { + "address": address, + "mode": "Edit", + }, + )!.then((value) { if (value == true) { controller.getUser(); } }); }, - child: SvgPicture.asset("assets/icons/ic_edit_address.svg"), + child: SvgPicture.asset( + "assets/icons/ic_edit_address.svg", + ), ), ], ), ); }, - separatorBuilder: (BuildContext context, int index) { - return Padding(padding: const EdgeInsets.symmetric(vertical: 20), child: Divider(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, height: 1)); + separatorBuilder: ( + BuildContext context, + int index, + ) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 20, + ), + child: Divider( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + height: 1, + ), + ); }, ), ), @@ -127,9 +234,14 @@ class AddressListScreen extends StatelessWidget { ), ), bottomNavigationBar: Padding( - padding: const EdgeInsets.only(bottom: 30, left: 16, right: 16, top: 20), + padding: const EdgeInsets.only( + bottom: 30, + left: 16, + right: 16, + top: 20, + ), child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Add New Address", onPress: () { Get.to(EnterManuallyLocationScreen())!.then((value) { @@ -140,7 +252,15 @@ class AddressListScreen extends StatelessWidget { }, isRight: false, isCenter: true, - icon: SvgPicture.asset(AppAssets.icPlus, width: 20, height: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.greyDark900), + icon: SvgPicture.asset( + AppAssets.icPlus, + width: 20, + height: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.greyDark900, + ), color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50, ), diff --git a/lib/screen_ui/location_enable_screens/enter_manually_location.dart b/lib/screen_ui/location_enable_screens/enter_manually_location.dart index 83046f1..ff1f41e 100644 --- a/lib/screen_ui/location_enable_screens/enter_manually_location.dart +++ b/lib/screen_ui/location_enable_screens/enter_manually_location.dart @@ -9,8 +9,7 @@ import 'package:customer/widget/place_picker/selected_location_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../controllers/enter_manually_location_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; @@ -40,23 +39,50 @@ class EnterManuallyLocationScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - controller.mode == "Edit" ? "Edit Address".tr() : "Add a New Address".tr(), - style: AppThemeData.boldTextStyle(fontSize: 24, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller.mode == "Edit" + ? "Edit Address".tr() + : "Add a New Address".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), - Text("Enter your location details so we can deliver your orders quickly and accurately.".tr(), style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.grey600)), + Text( + "Enter your location details so we can deliver your orders quickly and accurately." + .tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.grey600, + ), + ), const SizedBox(height: 24), Row( children: [ - Expanded(child: Text("Set as Default Address".tr(), style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.grey600))), + Expanded( + child: Text( + "Set as Default Address".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.grey600, + ), + ), + ), Transform.scale( - scale: 0.7, // Decrease the size (try 0.5, 0.6, etc.) + scale: + 0.7, // Decrease the size (try 0.5, 0.6, etc.) child: Switch( value: controller.isDefault.value, onChanged: (value) { @@ -74,23 +100,53 @@ class EnterManuallyLocationScreen extends StatelessWidget { context: context, onTap: () async { if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lat = + firstPlace.coordinates.latitude; + final lng = + firstPlace.coordinates.longitude; final address = firstPlace.address; - controller.localityEditingController.value.text = address.toString(); - controller.location.value = UserLocation(latitude: lat, longitude: lng); + controller + .localityEditingController + .value + .text = address.toString(); + controller.location.value = UserLocation( + latitude: lat, + longitude: lng, + ); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - controller.localityEditingController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.location.value = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); + controller + .localityEditingController + .value + .text = Utils.formatAddress( + selectedLocation: + selectedLocationModel, + ); + controller + .location + .value = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, + ); } }); } @@ -109,23 +165,55 @@ class EnterManuallyLocationScreen extends StatelessWidget { context: context, onTap: () async { if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lat = + firstPlace.coordinates.latitude; + final lng = + firstPlace.coordinates.longitude; final address = firstPlace.address; - controller.localityEditingController.value.text = address.toString(); - controller.location.value = UserLocation(latitude: lat, longitude: lng); + controller + .localityEditingController + .value + .text = address.toString(); + controller + .location + .value = UserLocation( + latitude: lat, + longitude: lng, + ); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - controller.localityEditingController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.location.value = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); + controller + .localityEditingController + .value + .text = Utils.formatAddress( + selectedLocation: + selectedLocationModel, + ); + controller + .location + .value = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, + ); Get.back(); } }); @@ -133,20 +221,50 @@ class EnterManuallyLocationScreen extends StatelessWidget { }, ); }, - child: Padding(padding: const EdgeInsets.only(right: 10), child: Icon(Icons.gps_fixed, size: 24, color: AppThemeData.ecommerce300)), + child: Padding( + padding: const EdgeInsets.only(right: 10), + child: Icon( + Icons.gps_fixed, + size: 24, + color: AppThemeData.ecommerce300, + ), + ), ), ), ), const SizedBox(height: 15), - TextFieldWidget(title: "Flat/House/Floor/Building*".tr(), hintText: "Enter address details".tr(), controller: controller.houseBuildingTextEditingController.value), + TextFieldWidget( + title: "Flat/House/Floor/Building*".tr(), + hintText: "Enter address details".tr(), + controller: + controller + .houseBuildingTextEditingController + .value, + ), const SizedBox(height: 15), - TextFieldWidget(title: "Area/Sector/Locality*".tr(), hintText: "Enter area/locality".tr(), controller: controller.localityEditingController.value), + TextFieldWidget( + title: "Area/Sector/Locality*".tr(), + hintText: "Enter area/locality".tr(), + controller: + controller.localityEditingController.value, + ), const SizedBox(height: 15), - TextFieldWidget(title: "Nearby Landmark".tr(), hintText: "Add a landmark".tr(), controller: controller.landmarkEditingController.value), + TextFieldWidget( + title: "Nearby Landmark".tr(), + hintText: "Add a landmark".tr(), + controller: + controller.landmarkEditingController.value, + ), const SizedBox(height: 30), Container(height: 1, color: AppThemeData.grey200), const SizedBox(height: 25), - Text("Save Address As".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900)), + Text( + "Save Address As".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), + ), const SizedBox(height: 10), Wrap( spacing: 10, @@ -155,17 +273,37 @@ class EnterManuallyLocationScreen extends StatelessWidget { .map( (item) => GestureDetector( onTap: () { - controller.selectedSaveAs.value = item; + controller.selectedSaveAs.value = + item; }, child: Container( decoration: BoxDecoration( - color: controller.selectedSaveAs.value == item ? AppThemeData.primary300 : AppThemeData.grey100, - borderRadius: BorderRadius.circular(10), + color: + controller + .selectedSaveAs + .value == + item + ? AppThemeData.primary300 + : AppThemeData.grey100, + borderRadius: BorderRadius.circular( + 10, + ), + ), + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 10, ), - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: Text( controller.getLocalizedSaveAs(item), - style: AppThemeData.mediumTextStyle(color: controller.selectedSaveAs.value == item ? AppThemeData.grey50 : AppThemeData.grey600), + style: AppThemeData.mediumTextStyle( + color: + controller + .selectedSaveAs + .value == + item + ? AppThemeData.grey50 + : AppThemeData.grey600, + ), textAlign: TextAlign.center, ), ), @@ -175,55 +313,111 @@ class EnterManuallyLocationScreen extends StatelessWidget { ), const SizedBox(height: 30), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Save Address".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () async { - if (controller.location.value.latitude == null || controller.location.value.longitude == null) { - ShowToastDialog.showToast("Please select Location".tr()); - } else if (controller.houseBuildingTextEditingController.value.text.isEmpty) { - ShowToastDialog.showToast("Please Enter Flat / House / Floor / Building".tr()); - } else if (controller.localityEditingController.value.text.isEmpty) { - ShowToastDialog.showToast("Please Enter Area / Sector / Locality".tr()); + if (controller.location.value.latitude == null || + controller.location.value.longitude == null) { + ShowToastDialog.showToast( + "Please select Location".tr(), + ); + } else if (controller + .houseBuildingTextEditingController + .value + .text + .isEmpty) { + ShowToastDialog.showToast( + "Please Enter Flat / House / Floor / Building" + .tr(), + ); + } else if (controller + .localityEditingController + .value + .text + .isEmpty) { + ShowToastDialog.showToast( + "Please Enter Area / Sector / Locality".tr(), + ); } else { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); //Common values - controller.shippingModel.value.location = controller.location.value; - controller.shippingModel.value.addressAs = controller.selectedSaveAs.value; - controller.shippingModel.value.address = controller.houseBuildingTextEditingController.value.text; - controller.shippingModel.value.locality = controller.localityEditingController.value.text; - controller.shippingModel.value.landmark = controller.landmarkEditingController.value.text; + controller.shippingModel.value.location = + controller.location.value; + controller.shippingModel.value.addressAs = + controller.selectedSaveAs.value; + controller.shippingModel.value.address = + controller + .houseBuildingTextEditingController + .value + .text; + controller.shippingModel.value.locality = + controller + .localityEditingController + .value + .text; + controller.shippingModel.value.landmark = + controller + .landmarkEditingController + .value + .text; if (controller.mode.value == "Edit") { //Edit Mode controller.shippingAddressList.value = - controller.shippingAddressList.map((address) { - if (address.id == controller.shippingModel.value.id) { - return controller.shippingModel.value; // replace existing one + controller.shippingAddressList.map(( + address, + ) { + if (address.id == + controller.shippingModel.value.id) { + return controller + .shippingModel + .value; // replace existing one } return address; }).toList(); - Constant.selectedLocation = controller.shippingModel.value; + Constant.selectedLocation = + controller.shippingModel.value; } else { //Add Mode - controller.shippingModel.value.id = Constant.getUuid(); - controller.shippingModel.value.isDefault = controller.shippingAddressList.isEmpty ? true : false; - controller.shippingAddressList.add(controller.shippingModel.value); + controller.shippingModel.value.id = + Constant.getUuid(); + controller.shippingModel.value.isDefault = + controller.shippingAddressList.isEmpty + ? true + : false; + controller.shippingAddressList.add( + controller.shippingModel.value, + ); } //Handle default address switch if (controller.isDefault.value) { controller.shippingAddressList.value = - controller.shippingAddressList.map((address) { - address.isDefault = address.id == controller.shippingModel.value.id ? true : false; + controller.shippingAddressList.map(( + address, + ) { + address.isDefault = + address.id == + controller + .shippingModel + .value + .id + ? true + : false; return address; }).toList(); } - controller.userModel.value.shippingAddress = controller.shippingAddressList; - await FireStoreUtils.updateUser(controller.userModel.value); + controller.userModel.value.shippingAddress = + controller.shippingAddressList; + await FireStoreUtils.updateUser( + controller.userModel.value, + ); ShowToastDialog.closeLoader(); Get.back(result: true); diff --git a/lib/screen_ui/location_enable_screens/location_permission_screen.dart b/lib/screen_ui/location_enable_screens/location_permission_screen.dart index b3903e1..7577eea 100644 --- a/lib/screen_ui/location_enable_screens/location_permission_screen.dart +++ b/lib/screen_ui/location_enable_screens/location_permission_screen.dart @@ -14,8 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../constant/assets.dart'; import '../../utils/utils.dart'; @@ -41,7 +40,13 @@ class LocationPermissionScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 25), child: Text( "Enable Location for a Personalized Experience".tr(), - style: AppThemeData.boldTextStyle(fontSize: 24, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), textAlign: TextAlign.center, ), ), @@ -49,14 +54,21 @@ class LocationPermissionScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 50), child: Text( - "Allow location access to discover beauty stores and services near you.".tr(), - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + "Allow location access to discover beauty stores and services near you." + .tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), textAlign: TextAlign.center, ), ), const SizedBox(height: 30), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Use current location".tr(), onPress: () async { Constant.checkPermission( @@ -66,34 +78,51 @@ class LocationPermissionScreen extends StatelessWidget { ShippingAddress addressModel = ShippingAddress(); try { await Geolocator.requestPermission(); - Position newLocalData = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); - await placemarkFromCoordinates(newLocalData.latitude, newLocalData.longitude).then((valuePlaceMaker) { + Position newLocalData = + await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.high, + ); + await placemarkFromCoordinates( + newLocalData.latitude, + newLocalData.longitude, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; addressModel.addressAs = "Home"; - addressModel.location = UserLocation(latitude: newLocalData.latitude, longitude: newLocalData.longitude); + addressModel.location = UserLocation( + latitude: newLocalData.latitude, + longitude: newLocalData.longitude, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; addressModel.locality = currentLocation; }); Constant.selectedLocation = addressModel; - Constant.currentLocation = await Utils.getCurrentLocation(); + Constant.currentLocation = + await Utils.getCurrentLocation(); ShowToastDialog.closeLoader(); Get.offAll(const ServiceListScreen()); } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; addressModel.addressAs = "Home"; - addressModel.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + addressModel.location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; addressModel.locality = currentLocation; }); Constant.selectedLocation = addressModel; - Constant.currentLocation = await Utils.getCurrentLocation(); + Constant.currentLocation = + await Utils.getCurrentLocation(); ShowToastDialog.closeLoader(); @@ -107,7 +136,7 @@ class LocationPermissionScreen extends StatelessWidget { ), const SizedBox(height: 10), RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Set from map".tr(), onPress: () async { Constant.checkPermission( @@ -117,7 +146,9 @@ class LocationPermissionScreen extends StatelessWidget { ShippingAddress addressModel = ShippingAddress(); try { await Geolocator.requestPermission(); - await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); + await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.high, + ); ShowToastDialog.closeLoader(); if (Constant.selectedMapType == 'osm') { final result = await Get.to(() => MapPickerPage()); @@ -129,18 +160,29 @@ class LocationPermissionScreen extends StatelessWidget { addressModel.addressAs = "Home"; addressModel.locality = address.toString(); - addressModel.location = UserLocation(latitude: lat, longitude: lng); + addressModel.location = UserLocation( + latitude: lat, + longitude: lng, + ); Constant.selectedLocation = addressModel; Get.offAll(const ServiceListScreen()); } } else { Get.to(LocationPickerScreen())!.then((value) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel selectedLocationModel = + value; addressModel.addressAs = "Home"; - addressModel.locality = Utils.formatAddress(selectedLocation: selectedLocationModel); - addressModel.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); + addressModel.locality = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + addressModel.location = UserLocation( + latitude: + selectedLocationModel.latLng!.latitude, + longitude: + selectedLocationModel.latLng!.longitude, + ); Constant.selectedLocation = addressModel; Get.offAll(const ServiceListScreen()); @@ -148,10 +190,16 @@ class LocationPermissionScreen extends StatelessWidget { }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; addressModel.addressAs = "Home"; - addressModel.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + addressModel.location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; addressModel.locality = currentLocation; @@ -181,7 +229,16 @@ class LocationPermissionScreen extends StatelessWidget { } }); }, - child: Text("Enter Manually location".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + "Enter Manually location".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), ], ), diff --git a/lib/screen_ui/maintenance_mode_screen/maintenance_mode_screen.dart b/lib/screen_ui/maintenance_mode_screen/maintenance_mode_screen.dart index 38ae3cc..7a67cfc 100644 --- a/lib/screen_ui/maintenance_mode_screen/maintenance_mode_screen.dart +++ b/lib/screen_ui/maintenance_mode_screen/maintenance_mode_screen.dart @@ -1,7 +1,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class MaintenanceModeScreen extends StatelessWidget { const MaintenanceModeScreen({super.key}); @@ -14,14 +14,24 @@ class MaintenanceModeScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Center(child: Image.asset('assets/images/maintenance.png', height: 200, width: 200)), + Center( + child: Image.asset( + 'assets/images/maintenance.png', + height: 200, + width: 200, + ), + ), const SizedBox(height: 20), - Text("We'll be back soon!".tr(), style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), + Text( + "We'll be back soon!".tr(), + style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), const SizedBox(height: 10), Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Text( - "Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!".tr(), + "Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!" + .tr(), textAlign: TextAlign.center, style: const TextStyle(fontSize: 16), ), diff --git a/lib/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart b/lib/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart index 87b1649..8585299 100644 --- a/lib/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart +++ b/lib/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart @@ -9,8 +9,7 @@ import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -30,20 +29,27 @@ class AllAdvertisementScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( "Highlights for you".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), body: controller.isLoading.value ? Constant.loader() : controller.advertisementList.isEmpty - ? Constant.showEmptyView(message: "Highlights for you not found.".tr()) + ? Constant.showEmptyView( + message: "Highlights for you not found.".tr(), + ) : Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: ListView.builder( @@ -51,7 +57,10 @@ class AllAdvertisementScreen extends StatelessWidget { itemCount: controller.advertisementList.length, padding: EdgeInsets.all(0), itemBuilder: (BuildContext context, int index) { - return AdvertisementCard(controller: controller, model: controller.advertisementList[index]); + return AdvertisementCard( + controller: controller, + model: controller.advertisementList[index], + ); }, ), ), @@ -65,7 +74,11 @@ class AdvertisementCard extends StatelessWidget { final AdvertisementModel model; final AdvertisementListController controller; - const AdvertisementCard({super.key, required this.controller, required this.model}); + const AdvertisementCard({ + super.key, + required this.controller, + required this.model, + }); @override Widget build(BuildContext context) { @@ -74,9 +87,14 @@ class AdvertisementCard extends StatelessWidget { return InkWell( onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(model.vendorId!); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + model.vendorId!, + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Container( margin: EdgeInsets.only(bottom: 16), @@ -84,7 +102,14 @@ class AdvertisementCard extends StatelessWidget { decoration: BoxDecoration( color: isDark ? AppThemeData.info600 : AppThemeData.surface, borderRadius: BorderRadius.circular(16), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: isDark ? 6 : 2, spreadRadius: 0, offset: Offset(0, isDark ? 3 : 1))], + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: isDark ? 6 : 2, + spreadRadius: 0, + offset: Offset(0, isDark ? 3 : 1), + ), + ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -93,18 +118,32 @@ class AdvertisementCard extends StatelessWidget { children: [ model.type == 'restaurant_promotion' ? ClipRRect( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - child: NetworkImageWidget(imageUrl: model.coverImage ?? '', height: 150, width: double.infinity, fit: BoxFit.cover), + borderRadius: BorderRadius.vertical( + top: Radius.circular(16), + ), + child: NetworkImageWidget( + imageUrl: model.coverImage ?? '', + height: 150, + width: double.infinity, + fit: BoxFit.cover, + ), ) - : VideoAdvWidget(url: model.video ?? '', height: 150, width: double.infinity), - if (model.type != 'video_promotion' && model.vendorId != null && (model.showRating == true || model.showReview == true)) + : VideoAdvWidget( + url: model.video ?? '', + height: 150, + width: double.infinity, + ), + if (model.type != 'video_promotion' && + model.vendorId != null && + (model.showRating == true || model.showReview == true)) Positioned( bottom: 8, right: 8, child: FutureBuilder( future: FireStoreUtils.getVendorById(model.vendorId!), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot.connectionState == + ConnectionState.waiting) { return const SizedBox(); } else { if (snapshot.hasError) { @@ -114,16 +153,42 @@ class AdvertisementCard extends StatelessWidget { } else { VendorModel vendorModel = snapshot.data!; return Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(120), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), child: Row( children: [ - if (model.showRating == true) SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), - if (model.showRating == true) const SizedBox(width: 5), + if (model.showRating == true) + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), + if (model.showRating == true) + const SizedBox(width: 5), Text( "${model.showRating == true ? Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString()) : ''}${model.showRating == true && model.showReview == true ? ' ' : ''}${model.showReview == true ? '(${vendorModel.reviewsCount!.toStringAsFixed(0)})' : ''}", - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ], ), @@ -142,7 +207,15 @@ class AdvertisementCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ if (model.type == 'restaurant_promotion') - ClipRRect(borderRadius: BorderRadius.circular(30), child: NetworkImageWidget(imageUrl: model.profileImage ?? '', height: 50, width: 50, fit: BoxFit.cover)), + ClipRRect( + borderRadius: BorderRadius.circular(30), + child: NetworkImageWidget( + imageUrl: model.profileImage ?? '', + height: 50, + width: 50, + fit: BoxFit.cover, + ), + ), SizedBox(width: 8), Expanded( child: Column( @@ -150,12 +223,26 @@ class AdvertisementCard extends StatelessWidget { children: [ Text( model.title ?? '', - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontWeight: FontWeight.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + fontWeight: FontWeight.bold, + ), overflow: TextOverflow.ellipsis, ), Text( model.description ?? '', - style: TextStyle(fontSize: 14, fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey400 : AppThemeData.grey600), + style: TextStyle( + fontSize: 14, + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey600, + ), overflow: TextOverflow.ellipsis, maxLines: 2, ), @@ -166,25 +253,74 @@ class AdvertisementCard extends StatelessWidget { ? Obx( () => IconButton( icon: - controller.favouriteList.where((p0) => p0.restaurantId == model.vendorId).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey400 : AppThemeData.grey600, BlendMode.srcIn)), + controller.favouriteList + .where( + (p0) => + p0.restaurantId == model.vendorId, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + colorFilter: ColorFilter.mode( + isDark + ? AppThemeData.grey400 + : AppThemeData.grey600, + BlendMode.srcIn, + ), + ), onPressed: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == model.vendorId).isNotEmpty) { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: model.vendorId, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.removeWhere((item) => item.restaurantId == model.vendorId); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); + if (controller.favouriteList + .where( + (p0) => p0.restaurantId == model.vendorId, + ) + .isNotEmpty) { + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: model.vendorId, + userId: FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.removeWhere( + (item) => item.restaurantId == model.vendorId, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: model.vendorId, userId: FireStoreUtils.getCurrentUid()); + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: model.vendorId, + userId: FireStoreUtils.getCurrentUid(), + ); controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } }, ), ) : Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))), - child: Padding(padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), child: Icon(Icons.arrow_forward, size: 20, color: AppThemeData.primary300)), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + child: Icon( + Icons.arrow_forward, + size: 20, + color: AppThemeData.primary300, + ), + ), ), ], ), diff --git a/lib/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart b/lib/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart index acf9906..85e802c 100644 --- a/lib/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart +++ b/lib/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart @@ -19,8 +19,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../models/user_model.dart'; import '../../../service/fire_store_utils.dart'; @@ -41,8 +40,12 @@ class CartScreen extends StatelessWidget { init: CartController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + ), body: cartItem.isEmpty ? Constant.showEmptyView(message: "Item Not available".tr()) @@ -53,17 +56,28 @@ class CartScreen extends StatelessWidget { controller.selectedFoodType.value == 'TakeAway' ? const SizedBox() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: InkWell( onTap: () { Get.to(AddressListScreen())!.then((value) { if (value != null) { ShippingAddress shippingAddress = value; - if (Constant.checkZoneCheck(shippingAddress.location!.latitude ?? 0.0, shippingAddress.location!.longitude ?? 0.0)) { - controller.selectedAddress.value = shippingAddress; + if (Constant.checkZoneCheck( + shippingAddress.location!.latitude ?? + 0.0, + shippingAddress.location!.longitude ?? + 0.0, + )) { + controller.selectedAddress.value = + shippingAddress; controller.calculatePrice(); } else { - ShowToastDialog.showToast("Service not available in this area".tr()); + ShowToastDialog.showToast( + "Service not available in this area" + .tr(), + ); } } }); @@ -71,33 +85,71 @@ class CartScreen extends StatelessWidget { child: Column( children: [ Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 8, + ), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_send_one.svg"), + SvgPicture.asset( + "assets/icons/ic_send_one.svg", + ), const SizedBox(width: 10), Expanded( child: Text( - controller.selectedAddress.value.addressAs.toString(), + controller + .selectedAddress + .value + .addressAs + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontSize: 16, + ), ), ), - SvgPicture.asset("assets/icons/ic_down.svg"), + SvgPicture.asset( + "assets/icons/ic_down.svg", + ), ], ), const SizedBox(height: 5), Text( - controller.selectedAddress.value.getFullAddress(), + controller.selectedAddress.value + .getFullAddress(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -111,87 +163,189 @@ class CartScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), child: ListView.separated( shrinkWrap: true, padding: EdgeInsets.zero, itemCount: cartItem.length, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - CartProductModel cartProductModel = cartItem[index]; + CartProductModel cartProductModel = + cartItem[index]; ProductModel? productModel; - FireStoreUtils.getProductById(cartProductModel.id!.split('~').first).then((value) { + FireStoreUtils.getProductById( + cartProductModel.id!.split('~').first, + ).then((value) { productModel = value; }); - print("cartItem[index] :: ${cartItem[index].extras} ::${cartItem[index].extrasPrice}"); + print( + "cartItem[index] :: ${cartItem[index].extras} ::${cartItem[index].extrasPrice}", + ); return InkWell( onTap: () async { - await FireStoreUtils.getVendorById(productModel!.vendorID.toString()).then((value) { + await FireStoreUtils.getVendorById( + productModel!.vendorID.toString(), + ).then((value) { if (value != null) { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": value}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": value}, + ); } }); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: + const BorderRadius.all( + Radius.circular(16), + ), child: NetworkImageWidget( - imageUrl: cartProductModel.photo.toString(), - height: Responsive.height(10, context), - width: Responsive.width(20, context), + imageUrl: + cartProductModel.photo + .toString(), + height: Responsive.height( + 10, + context, + ), + width: Responsive.width( + 20, + context, + ), fit: BoxFit.cover, ), ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${cartProductModel.name}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), - double.parse(cartProductModel.discountPrice.toString()) <= 0 + double.parse( + cartProductModel + .discountPrice + .toString(), + ) <= + 0 ? Text( - Constant.amountShow(amount: cartProductModel.price), + Constant.amountShow( + amount: + cartProductModel + .price, + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ) : Row( children: [ Text( - Constant.amountShow(amount: cartProductModel.discountPrice.toString()), + Constant.amountShow( + amount: + cartProductModel + .discountPrice + .toString(), + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), - const SizedBox(width: 5), + const SizedBox( + width: 5, + ), Text( - Constant.amountShow(amount: cartProductModel.price), + Constant.amountShow( + amount: + cartProductModel + .price, + ), style: TextStyle( fontSize: 14, - decoration: TextDecoration.lineThrough, - decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - color: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + decoration: + TextDecoration + .lineThrough, + decorationColor: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + color: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), ], @@ -201,76 +355,219 @@ class CartScreen extends StatelessWidget { ), Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFD1D5DB)), borderRadius: BorderRadius.circular(200)), + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFD1D5DB), + ), + borderRadius: + BorderRadius.circular( + 200, + ), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + padding: + const EdgeInsets.symmetric( + vertical: 5, + horizontal: 5, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, children: [ InkWell( onTap: () { - controller.addToCart(cartProductModel: cartProductModel, isIncrement: false, quantity: cartProductModel.quantity! - 1); + controller.addToCart( + cartProductModel: + cartProductModel, + isIncrement: false, + quantity: + cartProductModel + .quantity! - + 1, + ); }, - child: Icon(Icons.remove, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + child: Icon( + Icons.remove, + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), child: Text( - cartProductModel.quantity.toString(), - textAlign: TextAlign.start, + cartProductModel + .quantity + .toString(), + textAlign: + TextAlign.start, maxLines: 1, style: TextStyle( fontSize: 16, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + overflow: + TextOverflow + .ellipsis, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w500, + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, ), ), ), InkWell( onTap: () { - if (productModel!.itemAttribute != null) { - if (productModel!.itemAttribute!.variants!.where((element) => element.variantSku == cartProductModel.variantInfo!.variantSku).isNotEmpty) { + if (productModel! + .itemAttribute != + null) { + if (productModel! + .itemAttribute! + .variants! + .where( + (element) => + element + .variantSku == + cartProductModel + .variantInfo! + .variantSku, + ) + .isNotEmpty) { if (int.parse( - productModel!.itemAttribute!.variants! - .where((element) => element.variantSku == cartProductModel.variantInfo!.variantSku) + productModel! + .itemAttribute! + .variants! + .where( + ( + element, + ) => + element.variantSku == + cartProductModel.variantInfo!.variantSku, + ) .first .variantQuantity .toString(), ) > - (cartProductModel.quantity ?? 0) || + (cartProductModel + .quantity ?? + 0) || int.parse( - productModel!.itemAttribute!.variants! - .where((element) => element.variantSku == cartProductModel.variantInfo!.variantSku) + productModel! + .itemAttribute! + .variants! + .where( + ( + element, + ) => + element.variantSku == + cartProductModel.variantInfo!.variantSku, + ) .first .variantQuantity .toString(), ) == -1) { - controller.addToCart(cartProductModel: cartProductModel, isIncrement: true, quantity: cartProductModel.quantity! + 1); + controller.addToCart( + cartProductModel: + cartProductModel, + isIncrement: + true, + quantity: + cartProductModel + .quantity! + + 1, + ); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock" + .tr(), + ); } } else { - if ((productModel!.quantity ?? 0) > (cartProductModel.quantity ?? 0) || productModel!.quantity == -1) { - controller.addToCart(cartProductModel: cartProductModel, isIncrement: true, quantity: cartProductModel.quantity! + 1); + if ((productModel! + .quantity ?? + 0) > + (cartProductModel + .quantity ?? + 0) || + productModel! + .quantity == + -1) { + controller.addToCart( + cartProductModel: + cartProductModel, + isIncrement: + true, + quantity: + cartProductModel + .quantity! + + 1, + ); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock" + .tr(), + ); } } } else { - if ((productModel!.quantity ?? 0) > (cartProductModel.quantity ?? 0) || productModel!.quantity == -1) { - controller.addToCart(cartProductModel: cartProductModel, isIncrement: true, quantity: cartProductModel.quantity! + 1); + if ((productModel! + .quantity ?? + 0) > + (cartProductModel + .quantity ?? + 0) || + productModel! + .quantity == + -1) { + controller.addToCart( + cartProductModel: + cartProductModel, + isIncrement: + true, + quantity: + cartProductModel + .quantity! + + 1, + ); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock" + .tr(), + ); } } }, - child: Icon(Icons.add, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + child: Icon( + Icons.add, + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + ), ), ], ), @@ -278,47 +575,112 @@ class CartScreen extends StatelessWidget { ), ], ), - cartProductModel.variantInfo == null || cartProductModel.variantInfo!.variantOptions == null || cartProductModel.variantInfo!.variantOptions!.isEmpty + cartProductModel.variantInfo == + null || + cartProductModel + .variantInfo! + .variantOptions == + null || + cartProductModel + .variantInfo! + .variantOptions! + .isEmpty ? Container() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 5, + vertical: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Variants".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), const SizedBox(height: 5), Wrap( spacing: 6.0, runSpacing: 6.0, children: - List.generate(cartProductModel.variantInfo!.variantOptions!.length, (i) { - return Container( - decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), - child: Text( - "${cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)} : ${cartProductModel.variantInfo!.variantOptions![cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)]}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400), + List.generate( + cartProductModel + .variantInfo! + .variantOptions! + .length, + (i) { + return Container( + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), ), - ), - ); - }).toList(), + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: + 16, + vertical: + 5, + ), + child: Text( + "${cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)} : ${cartProductModel.variantInfo!.variantOptions![cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)]}", + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + ), + ), + ), + ); + }, + ).toList(), ), ], ), ), - cartProductModel.extras == null || cartProductModel.extras!.isEmpty || cartProductModel.extrasPrice == '0' + cartProductModel.extras == null || + cartProductModel + .extras! + .isEmpty || + cartProductModel + .extrasPrice == + '0' ? const SizedBox() : Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ const SizedBox(height: 10), Row( @@ -326,16 +688,51 @@ class CartScreen extends StatelessWidget { Expanded( child: Text( "Addons".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( Constant.amountShow( - amount: (double.parse(cartProductModel.extrasPrice.toString()) * double.parse(cartProductModel.quantity.toString())).toString(), + amount: + (double.parse( + cartProductModel + .extrasPrice + .toString(), + ) * + double.parse( + cartProductModel + .quantity + .toString(), + )) + .toString(), + ), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontSize: 16, ), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), ), ], ), @@ -344,22 +741,55 @@ class CartScreen extends StatelessWidget { spacing: 6.0, runSpacing: 6.0, children: - List.generate(cartProductModel.extras!.length, (i) { - return Container( - decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), - child: Text( - cartProductModel.extras![i].toString(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400), + List.generate( + cartProductModel + .extras! + .length, + (i) { + return Container( + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), ), - ), - ); - }).toList(), + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: + 16, + vertical: + 5, + ), + child: Text( + cartProductModel + .extras![i] + .toString(), + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + ), + ), + ), + ); + }, + ).toList(), ), ], ), @@ -369,7 +799,17 @@ class CartScreen extends StatelessWidget { ); }, separatorBuilder: (context, index) { - return Padding(padding: const EdgeInsets.symmetric(vertical: 10), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)); + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 10, + ), + child: MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + ); }, ), ), @@ -382,44 +822,84 @@ class CartScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "${'Delivery Type'.tr()} (${controller.selectedFoodType.value})".tr(), + "${'Delivery Type'.tr()} (${controller.selectedFoodType.value})" + .tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 10), controller.selectedFoodType.value == 'TakeAway' ? const SizedBox() : Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Row( children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Instant Delivery".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontSize: 16, + ), ), const SizedBox(height: 5), Text( "Standard".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: + AppThemeData.medium, + fontSize: 12, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + ), ), ], ), ), Radio( - value: controller.deliveryType.value, + value: + controller.deliveryType.value, groupValue: "instant".tr(), - activeColor: AppThemeData.primary300, + activeColor: + AppThemeData.primary300, onChanged: (value) { - controller.deliveryType.value = "instant"; + controller.deliveryType.value = + "instant"; }, ), ], @@ -429,18 +909,28 @@ class CartScreen extends StatelessWidget { const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: InkWell( onTap: () { controller.deliveryType.value = "schedule"; BottomPicker.dateTime( onSubmit: (index) { - controller.scheduleDateTime.value = index; + controller.scheduleDateTime.value = + index; }, minDateTime: DateTime.now(), displaySubmitButton: true, pickerTitle: Text('Schedule Time'.tr()), - buttonSingleColor: AppThemeData.primary300, + buttonSingleColor: + AppThemeData.primary300, ).show(context); }, child: Padding( @@ -449,18 +939,38 @@ class CartScreen extends StatelessWidget { children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Schedule Time".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontSize: 16, + ), ), const SizedBox(height: 5), Text( "${'Your preferred time'.tr()} ${controller.deliveryType.value == "schedule" ? Constant.timestampToDateTime(Timestamp.fromDate(controller.scheduleDateTime.value)) : ""}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: + AppThemeData.medium, + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), ), ], ), @@ -470,16 +980,28 @@ class CartScreen extends StatelessWidget { groupValue: "schedule".tr(), activeColor: AppThemeData.primary300, onChanged: (value) { - controller.deliveryType.value = "schedule"; + controller.deliveryType.value = + "schedule"; BottomPicker.dateTime( - initialDateTime: controller.scheduleDateTime.value, + initialDateTime: + controller + .scheduleDateTime + .value, onSubmit: (index) { - controller.scheduleDateTime.value = index; + controller + .scheduleDateTime + .value = index; }, - minDateTime: controller.scheduleDateTime.value, + minDateTime: + controller + .scheduleDateTime + .value, displaySubmitButton: true, - pickerTitle: Text('Schedule Time'.tr()), - buttonSingleColor: AppThemeData.primary300, + pickerTitle: Text( + 'Schedule Time'.tr(), + ), + buttonSingleColor: + AppThemeData.primary300, ).show(context); }, ), @@ -500,7 +1022,14 @@ class CartScreen extends StatelessWidget { Text( "Offers & Benefits".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 10), InkWell( @@ -510,20 +1039,43 @@ class CartScreen extends StatelessWidget { child: Container( width: Responsive.width(100, context), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - shadows: const [BoxShadow(color: Color(0x14000000), blurRadius: 52, offset: Offset(0, 0), spreadRadius: 0)], + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + shadows: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 52, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Apply Coupons".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ), const SizedBox(height: 5), @@ -545,101 +1097,234 @@ class CartScreen extends StatelessWidget { Text( "Bill Details".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - shadows: const [BoxShadow(color: Color(0x14000000), blurRadius: 52, offset: Offset(0, 0), spreadRadius: 0)], + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + shadows: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 52, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Item totals".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.subTotal.value.toString()), + Constant.amountShow( + amount: + controller.subTotal.value + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), - controller.selectedFoodType.value == 'TakeAway' + controller.selectedFoodType.value == + 'TakeAway' ? const SizedBox() : Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Delivery Fee".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), - (controller.vendorModel.value.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true) + (controller + .vendorModel + .value + .isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true) ? Text( 'Free Delivery'.tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: AppThemeData.success400, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + AppThemeData + .success400, + fontSize: 16, + ), ) : Text( - Constant.amountShow(amount: controller.deliveryCharges.value.toString()), + Constant.amountShow( + amount: + controller + .deliveryCharges + .value + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Coupon Discount".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( "- (${Constant.amountShow(amount: controller.couponAmount.value.toString())})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.danger300 + : AppThemeData.danger300, + fontSize: 16, + ), ), ], ), - controller.vendorModel.value.specialDiscountEnable == true && Constant.specialDiscountOffer == true + controller + .vendorModel + .value + .specialDiscountEnable == + true && + Constant.specialDiscountOffer == + true ? Column( children: [ const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Special Discount".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( "- (${Constant.amountShow(amount: controller.specialDiscountAmount.value.toString())})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .danger300 + : AppThemeData + .danger300, + fontSize: 16, + ), ), ], ), @@ -647,63 +1332,135 @@ class CartScreen extends StatelessWidget { ) : const SizedBox(), const SizedBox(height: 10), - controller.selectedFoodType.value == 'TakeAway' || (controller.vendorModel.value.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true) + controller.selectedFoodType.value == + 'TakeAway' || + (controller + .vendorModel + .value + .isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true) ? const SizedBox() : Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Delivery Tips".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), - controller.deliveryTips.value == 0 + controller + .deliveryTips + .value == + 0 ? const SizedBox() : InkWell( onTap: () { - controller.deliveryTips.value = 0; - controller.calculatePrice(); + controller + .deliveryTips + .value = 0; + controller + .calculatePrice(); }, child: Text( "Remove".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ], ), ), Text( - Constant.amountShow(amount: controller.deliveryTips.toString()), + Constant.amountShow( + amount: + controller.deliveryTips + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), ListView.builder( itemCount: Constant.taxList.length, shrinkWrap: true, padding: EdgeInsets.zero, - physics: const NeverScrollableScrollPhysics(), + physics: + const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - TaxModel taxModel = Constant.taxList[index]; + TaxModel taxModel = + Constant.taxList[index]; return Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 5, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "${taxModel.title.toString()} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( @@ -711,12 +1468,34 @@ class CartScreen extends StatelessWidget { amount: Constant.calculateTax( amount: - (double.parse(controller.subTotal.value.toString()) - controller.couponAmount.value - controller.specialDiscountAmount.value).toString(), + (double.parse( + controller + .subTotal + .value + .toString(), + ) - + controller + .couponAmount + .value - + controller + .specialDiscountAmount + .value) + .toString(), taxModel: taxModel, ).toString(), ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), @@ -725,19 +1504,39 @@ class CartScreen extends StatelessWidget { ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "To Pay".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.totalAmount.value.toString()), + Constant.amountShow( + amount: + controller.totalAmount.value + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -748,10 +1547,15 @@ class CartScreen extends StatelessWidget { ], ), ), - controller.selectedFoodType.value == 'TakeAway' || (controller.vendorModel.value.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true) + controller.selectedFoodType.value == 'TakeAway' || + (controller.vendorModel.value.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == true) ? const SizedBox() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -759,32 +1563,67 @@ class CartScreen extends StatelessWidget { Text( "Thanks with a tip!".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - shadows: const [BoxShadow(color: Color(0x14000000), blurRadius: 52, offset: Offset(0, 0), spreadRadius: 0)], + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + shadows: const [ + BoxShadow( + color: Color(0x14000000), + blurRadius: 52, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( - "Around the clock, our delivery partners make it happen. Show gratitude with a tip..".tr(), + "Around the clock, our delivery partners make it happen. Show gratitude with a tip.." + .tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600), + style: TextStyle( + fontFamily: + AppThemeData.medium, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + ), ), ), const SizedBox(width: 10), - SvgPicture.asset("assets/images/ic_tips.svg"), + SvgPicture.asset( + "assets/images/ic_tips.svg", + ), ], ), const SizedBox(height: 20), @@ -793,7 +1632,9 @@ class CartScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - controller.deliveryTips.value = 20; + controller + .deliveryTips + .value = 20; controller.calculatePrice(); }, child: Container( @@ -802,25 +1643,47 @@ class CartScreen extends StatelessWidget { side: BorderSide( width: 1, color: - controller.deliveryTips.value == 20 - ? AppThemeData.primary300 + controller + .deliveryTips + .value == + 20 + ? AppThemeData + .primary300 : isDark - ? AppThemeData.grey800 - : AppThemeData.grey100, + ? AppThemeData + .grey800 + : AppThemeData + .grey100, ), - borderRadius: BorderRadius.circular(8), + borderRadius: + BorderRadius.circular( + 8, + ), ), ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: Center( child: Text( - Constant.amountShow(amount: "20"), + Constant.amountShow( + amount: "20", + ), style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, fontSize: 14, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w600, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w600, ), ), ), @@ -832,7 +1695,9 @@ class CartScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - controller.deliveryTips.value = 30; + controller + .deliveryTips + .value = 30; controller.calculatePrice(); }, child: Container( @@ -841,25 +1706,47 @@ class CartScreen extends StatelessWidget { side: BorderSide( width: 1, color: - controller.deliveryTips.value == 30 - ? AppThemeData.primary300 + controller + .deliveryTips + .value == + 30 + ? AppThemeData + .primary300 : isDark - ? AppThemeData.grey800 - : AppThemeData.grey100, + ? AppThemeData + .grey800 + : AppThemeData + .grey100, ), - borderRadius: BorderRadius.circular(8), + borderRadius: + BorderRadius.circular( + 8, + ), ), ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: Center( child: Text( - Constant.amountShow(amount: "30"), + Constant.amountShow( + amount: "30", + ), style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, fontSize: 14, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w600, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w600, ), ), ), @@ -871,7 +1758,9 @@ class CartScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - controller.deliveryTips.value = 40; + controller + .deliveryTips + .value = 40; controller.calculatePrice(); }, child: Container( @@ -880,25 +1769,47 @@ class CartScreen extends StatelessWidget { side: BorderSide( width: 1, color: - controller.deliveryTips.value == 40 - ? AppThemeData.primary300 + controller + .deliveryTips + .value == + 40 + ? AppThemeData + .primary300 : isDark - ? AppThemeData.grey800 - : AppThemeData.grey100, + ? AppThemeData + .grey800 + : AppThemeData + .grey100, ), - borderRadius: BorderRadius.circular(8), + borderRadius: + BorderRadius.circular( + 8, + ), ), ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: Center( child: Text( - Constant.amountShow(amount: "40"), + Constant.amountShow( + amount: "40", + ), style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, fontSize: 14, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w600, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w600, ), ), ), @@ -912,28 +1823,55 @@ class CartScreen extends StatelessWidget { onTap: () { showDialog( context: context, - builder: (BuildContext context) { - return tipsDialog(controller, isDark); + builder: ( + BuildContext context, + ) { + return tipsDialog( + controller, + isDark, + ); }, ); }, child: Container( decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100), - borderRadius: BorderRadius.circular(8), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + ), + borderRadius: + BorderRadius.circular( + 8, + ), ), ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: Center( child: Text( 'Other'.tr(), style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, fontSize: 14, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w600, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w600, ), ), ), @@ -953,7 +1891,16 @@ class CartScreen extends StatelessWidget { const SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column(children: [TextFieldWidget(title: 'Remarks'.tr(), controller: controller.reMarkController.value, hintText: 'Write remarks for the store'.tr(), maxLine: 4)]), + child: Column( + children: [ + TextFieldWidget( + title: 'Remarks'.tr(), + controller: controller.reMarkController.value, + hintText: 'Write remarks for the store'.tr(), + maxLine: 4, + ), + ], + ), ), ], ), @@ -962,8 +1909,12 @@ class CartScreen extends StatelessWidget { cartItem.isEmpty ? null : Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), - height: controller.isCashbackApply.value == true ? 150 : 100, + decoration: BoxDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + ), + height: + controller.isCashbackApply.value == true ? 150 : 100, child: Column( children: [ if (controller.isCashbackApply.value == true) @@ -974,77 +1925,240 @@ class CartScreen extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only(top: 8), - child: Text("Cashback Offer".tr(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontSize: 13)), + child: Text( + "Cashback Offer".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontSize: 13, + ), + ), ), Text( "${"Cashback Name :".tr()} ${controller.bestCashback.value.title ?? ''}", - style: TextStyle(color: AppThemeData.success300, fontFamily: AppThemeData.semiBold, fontSize: 13), + style: TextStyle( + color: AppThemeData.success300, + fontFamily: AppThemeData.semiBold, + fontSize: 13, + ), ), Text( "${"You will get".tr()} ${Constant.amountShow(amount: controller.bestCashback.value.cashbackValue?.toStringAsFixed(2))} ${"cashback after completing the order.".tr()}", - style: TextStyle(color: AppThemeData.success300, fontFamily: AppThemeData.semiBold, fontSize: 13), + style: TextStyle( + color: AppThemeData.success300, + fontFamily: AppThemeData.semiBold, + fontSize: 13, + ), ), ], ), ), Padding( - padding: EdgeInsets.only(left: 16, right: 16, top: controller.isCashbackApply.value == false ? 16 : 12, bottom: 20), + padding: EdgeInsets.only( + left: 16, + right: 16, + top: + controller.isCashbackApply.value == false + ? 16 + : 12, + bottom: 20, + ), child: Row( children: [ Expanded( flex: 2, child: InkWell( onTap: () { - Get.to(const SelectPaymentScreen())?.then((v) { + Get.to(const SelectPaymentScreen())?.then(( + v, + ) { controller.getCashback(); }); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - controller.selectedPaymentMethod.value == '' - ? cardDecoration(controller, PaymentGateway.wallet, isDark, "") - : controller.selectedPaymentMethod.value == PaymentGateway.wallet.name - ? cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png") - : controller.selectedPaymentMethod.value == PaymentGateway.cod.name - ? cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png") - : controller.selectedPaymentMethod.value == PaymentGateway.stripe.name - ? cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png") - : controller.selectedPaymentMethod.value == PaymentGateway.paypal.name - ? cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payStack.name - ? cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png") - : controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name - ? cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png") - : controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name - ? cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png") - : controller.selectedPaymentMethod.value == PaymentGateway.payFast.name - ? cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png") - : controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name - ? cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png") - : controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name - ? cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png") - : controller.selectedPaymentMethod.value == PaymentGateway.xendit.name - ? cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png") - : cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"), + controller.selectedPaymentMethod.value == + '' + ? cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.wallet.name + ? cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.cod.name + ? cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.stripe.name + ? cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.paypal.name + ? cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.payStack.name + ? cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.mercadoPago.name + ? cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.flutterWave.name + ? cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.payFast.name + ? cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.midTrans.name + ? cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.orangeMoney.name + ? cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ) + : controller + .selectedPaymentMethod + .value == + PaymentGateway.xendit.name + ? cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ) + : cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), const SizedBox(width: 10), Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Pay Via".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontSize: 12), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontSize: 12, + ), ), - controller.selectedPaymentMethod.value == '' - ? Padding(padding: const EdgeInsets.only(top: 4), child: Container(width: 60, height: 12, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100)) + controller + .selectedPaymentMethod + .value == + '' + ? Padding( + padding: const EdgeInsets.only( + top: 4, + ), + child: Container( + width: 60, + height: 12, + color: + isDark + ? AppThemeData.grey800 + : AppThemeData + .grey100, + ), + ) : Text( - controller.selectedPaymentMethod.value, + controller + .selectedPaymentMethod + .value, textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), @@ -1054,9 +2168,10 @@ class CartScreen extends StatelessWidget { ), Expanded( child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, textColor: - controller.selectedPaymentMethod.value != '' + controller.selectedPaymentMethod.value != + '' ? AppThemeData.surface : isDark ? AppThemeData.grey800 @@ -1064,61 +2179,176 @@ class CartScreen extends StatelessWidget { title: "Pay Now".tr(), height: 5, color: - controller.selectedPaymentMethod.value != '' + controller.selectedPaymentMethod.value != + '' ? AppThemeData.primary300 : isDark ? AppThemeData.grey800 : AppThemeData.grey100, fontSizes: 16, onPress: () async { - if ((controller.couponAmount.value >= 1) && (controller.couponAmount.value > controller.totalAmount.value)) { - ShowToastDialog.showToast("The total price must be greater than or equal to the coupon discount value for the code to apply. Please review your cart total.".tr()); + if ((controller.couponAmount.value >= 1) && + (controller.couponAmount.value > + controller.totalAmount.value)) { + ShowToastDialog.showToast( + "The total price must be greater than or equal to the coupon discount value for the code to apply. Please review your cart total." + .tr(), + ); return; } - if ((controller.specialDiscountAmount.value >= 1) && (controller.specialDiscountAmount.value > controller.totalAmount.value)) { - ShowToastDialog.showToast("The total price must be greater than or equal to the special discount value for the code to apply. Please review your cart total.".tr()); + if ((controller + .specialDiscountAmount + .value >= + 1) && + (controller + .specialDiscountAmount + .value > + controller.totalAmount.value)) { + ShowToastDialog.showToast( + "The total price must be greater than or equal to the special discount value for the code to apply. Please review your cart total." + .tr(), + ); return; } - if (controller.isOrderPlaced.value == false) { + if (controller.isOrderPlaced.value == + false) { controller.isOrderPlaced.value = true; await controller.getCashback(); - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.totalAmount.value.toString(), context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + if (controller + .selectedPaymentMethod + .value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.totalAmount.value + .toString(), + context, + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.cod.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.wallet.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.totalAmount.value.toString()), razorpayModel: controller.razorPayModel.value).then(( - value, - ) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.totalAmount.value.toString(), orderId: result.id); - } - }); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.totalAmount.value + .toString(), + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.totalAmount.value + .toString(), + ), + razorpayModel: + controller + .razorPayModel + .value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel + result = value; + controller.openCheckout( + amount: + controller + .totalAmount + .value + .toString(), + orderId: result.id, + ); + } + }); } else { controller.isOrderPlaced.value = false; - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } controller.isOrderPlaced.value = false; } @@ -1136,14 +2366,32 @@ class CartScreen extends StatelessWidget { ); } - Padding cardDecoration(CartController controller, PaymentGateway value, isDark, String image) { + Padding cardDecoration( + CartController controller, + PaymentGateway value, + isDark, + String image, + ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: Container( width: 40, height: 40, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: image == '' ? Container(color: isDark ? AppThemeData.grey800 : AppThemeData.grey100) : Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), + child: + image == '' + ? Container( + color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + ) + : Image.asset(image), + ), ), ); } @@ -1165,12 +2413,28 @@ class CartScreen extends StatelessWidget { TextFieldWidget( title: 'Tips Amount'.tr(), controller: controller.tipsController.value, - textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true), + textInputType: const TextInputType.numberWithOptions( + signed: true, + decimal: true, + ), textInputAction: TextInputAction.done, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9]'))], + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9]')), + ], prefix: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - child: Text(Constant.currencyModel!.symbol.tr(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontSize: 18)), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 14, + ), + child: Text( + Constant.currencyModel!.symbol.tr(), + style: TextStyle( + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontSize: 18, + ), + ), ), hintText: 'Enter Tips Amount'.tr(), ), @@ -1179,10 +2443,12 @@ class CartScreen extends StatelessWidget { children: [ Expanded( child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Cancel".tr(), - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, - textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark ? AppThemeData.grey700 : AppThemeData.grey200, + textColor: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, onPress: () async { Get.back(); }, @@ -1191,15 +2457,19 @@ class CartScreen extends StatelessWidget { const SizedBox(width: 20), Expanded( child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Add".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () async { if (controller.tipsController.value.text.isEmpty) { - ShowToastDialog.showToast("Please enter tips Amount".tr()); + ShowToastDialog.showToast( + "Please enter tips Amount".tr(), + ); } else { - controller.deliveryTips.value = double.parse(controller.tipsController.value.text); + controller.deliveryTips.value = double.parse( + controller.tipsController.value.text, + ); controller.calculatePrice(); Get.back(); } diff --git a/lib/screen_ui/multi_vendor_service/cart_screen/coupon_list_screen.dart b/lib/screen_ui/multi_vendor_service/cart_screen/coupon_list_screen.dart index 812e5df..4e7a57e 100644 --- a/lib/screen_ui/multi_vendor_service/cart_screen/coupon_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/cart_screen/coupon_list_screen.dart @@ -8,7 +8,7 @@ import 'package:customer/widget/my_separator.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -23,12 +23,22 @@ class CouponListScreen extends StatelessWidget { init: CartController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Coupon Code".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Coupon Code".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), bottom: PreferredSize( preferredSize: const Size.fromHeight(55), child: Padding( @@ -37,23 +47,44 @@ class CouponListScreen extends StatelessWidget { hintText: 'Enter coupon code'.tr(), controller: controller.couponCodeController.value, suffix: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), child: InkWell( onTap: () { - if (controller.couponCodeController.value.text.isEmpty) { - ShowToastDialog.showToast("Please enter coupon code".tr()); + if (controller + .couponCodeController + .value + .text + .isEmpty) { + ShowToastDialog.showToast( + "Please enter coupon code".tr(), + ); return; } - CouponModel? matchedCoupon = controller.couponList.firstWhereOrNull((coupon) => coupon.code!.toLowerCase() == controller.couponCodeController.value.text.toLowerCase()); + CouponModel? matchedCoupon = controller.couponList + .firstWhereOrNull( + (coupon) => + coupon.code!.toLowerCase() == + controller.couponCodeController.value.text + .toLowerCase(), + ); if (matchedCoupon != null) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: matchedCoupon); + double couponAmount = Constant.calculateDiscount( + amount: controller.subTotal.value.toString(), + offerModel: matchedCoupon, + ); if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = matchedCoupon; + controller.selectedCouponModel.value = + matchedCoupon; controller.calculatePrice(); Get.back(); } else { - ShowToastDialog.showToast("Coupon code not applied".tr()); + ShowToastDialog.showToast( + "Coupon code not applied".tr(), + ); } } else { ShowToastDialog.showToast("Invalid Coupon".tr()); @@ -62,7 +93,14 @@ class CouponListScreen extends StatelessWidget { child: Text( "Apply".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ), @@ -76,17 +114,32 @@ class CouponListScreen extends StatelessWidget { itemBuilder: (context, index) { CouponModel couponModel = controller.couponList[index]; return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Container( height: Responsive.height(16, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), child: Stack( children: [ - Image.asset("assets/images/ic_coupon_image.png", height: Responsive.height(16, context), fit: BoxFit.fill), + Image.asset( + "assets/images/ic_coupon_image.png", + height: Responsive.height(16, context), + fit: BoxFit.fill, + ), Padding( padding: const EdgeInsets.only(left: 10), child: Align( @@ -96,7 +149,14 @@ class CouponListScreen extends StatelessWidget { child: Text( "${couponModel.discountType == "Fix Price" ? Constant.amountShow(amount: couponModel.discount) : "${couponModel.discount}%"} ${'Off'.tr()}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), ), ), @@ -106,51 +166,98 @@ class CouponListScreen extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(6), color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(6), + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Text( "${couponModel.code}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ), ), const Expanded(child: SizedBox(height: 10)), InkWell( onTap: () { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: couponModel); + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: couponModel, + ); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = couponModel; + if (couponAmount < + controller.subTotal.value) { + controller.selectedCouponModel.value = + couponModel; controller.calculatePrice(); Get.back(); } else { - ShowToastDialog.showToast("Coupon code not applied".tr()); + ShowToastDialog.showToast( + "Coupon code not applied".tr(), + ); } }, child: Text( "Tap To Apply".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ], ), const SizedBox(height: 20), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 20), Text( "${couponModel.description}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), diff --git a/lib/screen_ui/multi_vendor_service/cart_screen/oder_placing_screens.dart b/lib/screen_ui/multi_vendor_service/cart_screen/oder_placing_screens.dart index 07796a8..cf4d0bc 100644 --- a/lib/screen_ui/multi_vendor_service/cart_screen/oder_placing_screens.dart +++ b/lib/screen_ui/multi_vendor_service/cart_screen/oder_placing_screens.dart @@ -10,8 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../dash_board_screens/dash_board_screen.dart'; @@ -26,8 +25,14 @@ class OrderPlacingScreen extends StatelessWidget { init: OrderPlacingController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: controller.isLoading.value ? Constant.loader() @@ -41,16 +46,41 @@ class OrderPlacingScreen extends StatelessWidget { Text( "Order Placed".tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey900, fontSize: 34, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey900, + fontSize: 34, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w400, + ), ), Text( - "Hang tight — your items are being delivered quickly and safely!".tr(), + "Hang tight — your items are being delivered quickly and safely!" + .tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 40), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Column( @@ -60,13 +90,26 @@ class OrderPlacingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_location.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_location.svg", + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 10), Expanded( child: Text( "Order ID".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 16, + ), ), ), ], @@ -75,7 +118,13 @@ class OrderPlacingScreen extends StatelessWidget { Text( controller.orderModel.value.id.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -90,21 +139,51 @@ class OrderPlacingScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Center(child: Image.asset("assets/images/ic_timer.gif", height: 140)), + Center( + child: Image.asset( + "assets/images/ic_timer.gif", + height: 140, + ), + ), const SizedBox(height: 20), Text( "Placing your order".tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey900, fontSize: 34, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey900, + fontSize: 34, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w400, + ), ), Text( - "Take a moment to review your order before proceeding to checkout.".tr(), + "Take a moment to review your order before proceeding to checkout." + .tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 40), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Column( @@ -114,22 +193,42 @@ class OrderPlacingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_location.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_location.svg", + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 10), Expanded( child: Text( "Delivery Address".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 16, + ), ), ), ], ), const SizedBox(height: 5), Text( - controller.orderModel.value.address!.getFullAddress(), + controller.orderModel.value.address! + .getFullAddress(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -137,7 +236,15 @@ class OrderPlacingScreen extends StatelessWidget { ), const SizedBox(height: 10), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Column( @@ -147,13 +254,27 @@ class OrderPlacingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_book.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn), height: 22), + SvgPicture.asset( + "assets/icons/ic_book.svg", + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + height: 22, + ), const SizedBox(width: 10), Expanded( child: Text( "Order Summary".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 16, + ), ), ), ], @@ -161,21 +282,47 @@ class OrderPlacingScreen extends StatelessWidget { const SizedBox(height: 5), ListView.builder( shrinkWrap: true, - itemCount: controller.orderModel.value.products!.length, + itemCount: + controller + .orderModel + .value + .products! + .length, itemBuilder: (context, index) { - CartProductModel cartProductModel = controller.orderModel.value.products![index]; + CartProductModel cartProductModel = + controller + .orderModel + .value + .products![index]; return Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${cartProductModel.quantity} x".tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey900, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey900, + fontSize: 14, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), Text( "${cartProductModel.name}".tr(), textAlign: TextAlign.start, - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey900, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey900, + fontSize: 14, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ], ); @@ -196,30 +343,39 @@ class OrderPlacingScreen extends StatelessWidget { child: controller.isPlacing.value ? RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Track Order".tr(), height: 5.5, color: AppThemeData.primary300, textColor: AppThemeData.grey50, fontSizes: 16, onPress: () async { - if (Constant.sectionConstantModel!.serviceTypeFlag == "ecommerce-service") { + if (Constant.sectionConstantModel!.serviceTypeFlag == + "ecommerce-service") { Get.offAll(const DashBoardEcommerceScreen()); - DashBoardEcommerceController controller = Get.put(DashBoardEcommerceController()); + DashBoardEcommerceController controller = Get.put( + DashBoardEcommerceController(), + ); controller.selectedIndex.value = 3; } else { Get.offAll(const DashBoardScreen()); - DashBoardController controller = Get.put(DashBoardController()); + DashBoardController controller = Get.put( + DashBoardController(), + ); controller.selectedIndex.value = 3; } }, ) : RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Track Order".tr(), height: 5.5, - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, - textColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + textColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, fontSizes: 16, onPress: () async {}, ), diff --git a/lib/screen_ui/multi_vendor_service/cart_screen/select_payment_screen.dart b/lib/screen_ui/multi_vendor_service/cart_screen/select_payment_screen.dart index ed41845..8817c3c 100644 --- a/lib/screen_ui/multi_vendor_service/cart_screen/select_payment_screen.dart +++ b/lib/screen_ui/multi_vendor_service/cart_screen/select_payment_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../wallet_screen/wallet_screen.dart'; diff --git a/lib/screen_ui/multi_vendor_service/cashback_screen/cashback_offers_list.dart b/lib/screen_ui/multi_vendor_service/cashback_screen/cashback_offers_list.dart index 92801a3..bc0aea5 100644 --- a/lib/screen_ui/multi_vendor_service/cashback_screen/cashback_offers_list.dart +++ b/lib/screen_ui/multi_vendor_service/cashback_screen/cashback_offers_list.dart @@ -3,8 +3,7 @@ import 'package:customer/controllers/cashback_controller.dart'; import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; class CashbackOffersListScreen extends StatelessWidget { @@ -21,8 +20,17 @@ class CashbackOffersListScreen extends StatelessWidget { appBar: AppBar( centerTitle: false, titleSpacing: 0, - title: Text("Cashback Offers".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + title: Text( + "Cashback Offers".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, ), body: controller.isLoading.value @@ -35,9 +43,18 @@ class CashbackOffersListScreen extends StatelessWidget { padding: const EdgeInsets.all(16), margin: const EdgeInsets.symmetric(vertical: 6), decoration: BoxDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, borderRadius: BorderRadius.circular(12), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 6, offset: const Offset(0, 3))], + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 6, + offset: const Offset(0, 3), + ), + ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -47,25 +64,57 @@ class CashbackOffersListScreen extends StatelessWidget { Expanded( child: Text( controller.cashbackList[index].title ?? '', - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), Text( - controller.cashbackList[index].cashbackType == 'Percent' + controller.cashbackList[index].cashbackType == + 'Percent' ? "${controller.cashbackList[index].cashbackAmount}%" - : Constant.amountShow(amount: "${controller.cashbackList[index].cashbackAmount}"), - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + : Constant.amountShow( + amount: + "${controller.cashbackList[index].cashbackAmount}", + ), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), const SizedBox(height: 6), Text( "${"Min spent".tr()} ${Constant.amountShow(amount: "${controller.cashbackList[index].minimumPurchaseAmount ?? 0.0}")} | ${"Valid till".tr()} ${Constant.timestampToDateTime2(controller.cashbackList[index].endDate!)}", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontSize: 14), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontSize: 14, + ), ), Text( "${"Maximum cashback up to".tr()} ${Constant.amountShow(amount: "${controller.cashbackList[index].maximumDiscount ?? 0.0}")}", - style: TextStyle(color: isDark ? AppThemeData.primary200 : AppThemeData.primary300, fontFamily: AppThemeData.regular, fontSize: 14), + style: TextStyle( + color: + isDark + ? AppThemeData.primary200 + : AppThemeData.primary300, + fontFamily: AppThemeData.regular, + fontSize: 14, + ), ), ], ), diff --git a/lib/screen_ui/multi_vendor_service/change langauge/change_language_screen.dart b/lib/screen_ui/multi_vendor_service/change langauge/change_language_screen.dart index bdbd0b0..537a753 100644 --- a/lib/screen_ui/multi_vendor_service/change langauge/change_language_screen.dart +++ b/lib/screen_ui/multi_vendor_service/change langauge/change_language_screen.dart @@ -6,8 +6,7 @@ import 'package:customer/utils/network_image_widget.dart'; import 'package:customer/utils/preferences.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import '../../../controllers/theme_controller.dart'; +import 'package:get/get.dart' hide Trans;import '../../../controllers/theme_controller.dart'; import '../../../service/localization_service.dart'; class ChangeLanguageScreen extends StatelessWidget { diff --git a/lib/screen_ui/multi_vendor_service/chat_screens/chat_screen.dart b/lib/screen_ui/multi_vendor_service/chat_screens/chat_screen.dart index 0a9f324..fc40a8a 100644 --- a/lib/screen_ui/multi_vendor_service/chat_screens/chat_screen.dart +++ b/lib/screen_ui/multi_vendor_service/chat_screens/chat_screen.dart @@ -11,7 +11,7 @@ import 'package:customer/utils/network_image_widget.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:get/get.dart' hide Trans; import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; import '../../../service/fire_store_utils.dart'; @@ -33,13 +33,18 @@ class ChatScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( controller.restaurantName.value, textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), body: Column( @@ -53,18 +58,28 @@ class ChatScreen extends StatelessWidget { controller: controller.scrollController, physics: const BouncingScrollPhysics(), itemBuilder: (context, documentSnapshots, index) { - ConversationModel inboxModel = ConversationModel.fromJson(documentSnapshots[index].data() as Map); - return chatItemView(isDark, inboxModel.senderId == FireStoreUtils.getCurrentUid(), inboxModel); + ConversationModel inboxModel = ConversationModel.fromJson( + documentSnapshots[index].data() as Map, + ); + return chatItemView( + isDark, + inboxModel.senderId == FireStoreUtils.getCurrentUid(), + inboxModel, + ); }, - onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()), + onEmpty: Constant.showEmptyView( + message: "No Conversion found".tr(), + ), // orderBy is compulsory to enable pagination query: FirebaseFirestore.instance .collection( controller.chatType.value == "Driver" ? 'chat_driver' - : controller.chatType.value == "Provider" || controller.chatType.value == "provider" + : controller.chatType.value == "Provider" || + controller.chatType.value == "provider" ? 'chat_provider' - : controller.chatType.value == "worker" || controller.chatType.value == "Worker" + : controller.chatType.value == "worker" || + controller.chatType.value == "Worker" ? 'chat_worker' : 'chat_store', ) @@ -79,7 +94,10 @@ class ChatScreen extends StatelessWidget { Container( color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -90,7 +108,9 @@ class ChatScreen extends StatelessWidget { onTap: () { onCameraClick(context, controller); }, - child: SvgPicture.asset("assets/icons/ic_picture_one.svg"), + child: SvgPicture.asset( + "assets/icons/ic_picture_one.svg", + ), ), Flexible( child: Padding( @@ -98,18 +118,39 @@ class ChatScreen extends StatelessWidget { child: TextField( textInputAction: TextInputAction.send, keyboardType: TextInputType.text, - textCapitalization: TextCapitalization.sentences, + textCapitalization: + TextCapitalization.sentences, controller: controller.messageController.value, decoration: InputDecoration( - contentPadding: const EdgeInsets.only(top: 3, left: 10), + contentPadding: const EdgeInsets.only( + top: 3, + left: 10, + ), focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, hintText: 'Type message here....'.tr(), ), onSubmitted: (value) async { - if (controller.messageController.value.text.isNotEmpty) { - controller.sendMessage(controller.messageController.value.text, null, '', 'text'); - Timer(const Duration(milliseconds: 500), () => controller.scrollController.jumpTo(controller.scrollController.position.maxScrollExtent)); + if (controller + .messageController + .value + .text + .isNotEmpty) { + controller.sendMessage( + controller.messageController.value.text, + null, + '', + 'text', + ); + Timer( + const Duration(milliseconds: 500), + () => controller.scrollController.jumpTo( + controller + .scrollController + .position + .maxScrollExtent, + ), + ); controller.messageController.value.clear(); } }, @@ -118,16 +159,36 @@ class ChatScreen extends StatelessWidget { ), InkWell( onTap: () { - if (controller.messageController.value.text.isNotEmpty) { - controller.sendMessage(controller.messageController.value.text, null, '', 'text'); + if (controller + .messageController + .value + .text + .isNotEmpty) { + controller.sendMessage( + controller.messageController.value.text, + null, + '', + 'text', + ); controller.messageController.value.clear(); // Timer(const Duration(milliseconds: 500), () => controller.scrollController.jumpTo(controller.scrollController.position.maxScrollExtent)); } }, child: Container( margin: const EdgeInsets.only(left: 10), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, borderRadius: BorderRadius.circular(30)), - child: Padding(padding: const EdgeInsets.all(10), child: SvgPicture.asset("assets/icons/ic_send.svg")), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + borderRadius: BorderRadius.circular(30), + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: SvgPicture.asset( + "assets/icons/ic_send.svg", + ), + ), ), ), ], @@ -157,23 +218,53 @@ class ChatScreen extends StatelessWidget { data.messageType == "text" ? Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomLeft: Radius.circular(12)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomLeft: Radius.circular(12), + ), color: AppThemeData.primary300, ), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - child: Text(data.message.toString(), style: const TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: AppThemeData.grey50)), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + child: Text( + data.message.toString(), + style: const TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: AppThemeData.grey50, + ), + ), ) : data.messageType == "image" ? ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomLeft: Radius.circular(12)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomLeft: Radius.circular(12), + ), child: Stack( alignment: Alignment.center, children: [ GestureDetector( onTap: () { - Get.to(FullScreenImageViewer(imageUrl: data.url!.url)); + Get.to( + FullScreenImageViewer( + imageUrl: data.url!.url, + ), + ); }, - child: Hero(tag: data.url!.url, child: NetworkImageWidget(imageUrl: data.url!.url, height: 100, width: 100, fit: BoxFit.cover)), + child: Hero( + tag: data.url!.url, + child: NetworkImageWidget( + imageUrl: data.url!.url, + height: 100, + width: 100, + fit: BoxFit.cover, + ), + ), ), ], ), @@ -183,13 +274,25 @@ class ChatScreen extends StatelessWidget { heroTag: data.id, backgroundColor: AppThemeData.primary300, onPressed: () { - Get.to(FullScreenVideoViewer(heroTag: data.id.toString(), videoUrl: data.url!.url)); + Get.to( + FullScreenVideoViewer( + heroTag: data.id.toString(), + videoUrl: data.url!.url, + ), + ); }, - child: const Icon(Icons.play_arrow, color: Colors.white), + child: const Icon( + Icons.play_arrow, + color: Colors.white, + ), ), const SizedBox(height: 5), Text( - DateFormat('MMM d, yyyy hh:mm aa').format(DateTime.fromMillisecondsSinceEpoch(data.createdAt!.millisecondsSinceEpoch)), + DateFormat('MMM d, yyyy hh:mm aa').format( + DateTime.fromMillisecondsSinceEpoch( + data.createdAt!.millisecondsSinceEpoch, + ), + ), style: const TextStyle(color: Colors.grey, fontSize: 12), ), ], @@ -201,25 +304,61 @@ class ChatScreen extends StatelessWidget { data.messageType == "text" ? Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomRight: Radius.circular(12)), - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + child: Text( + data.message.toString(), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - child: Text(data.message.toString(), style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)), ) : data.messageType == "image" ? ConstrainedBox( - constraints: const BoxConstraints(minWidth: 50, maxWidth: 200), + constraints: const BoxConstraints( + minWidth: 50, + maxWidth: 200, + ), child: ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomRight: Radius.circular(12)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomRight: Radius.circular(12), + ), child: Stack( alignment: Alignment.center, children: [ GestureDetector( onTap: () { - Get.to(FullScreenImageViewer(imageUrl: data.url!.url)); + Get.to( + FullScreenImageViewer( + imageUrl: data.url!.url, + ), + ); }, - child: Hero(tag: data.url!.url, child: NetworkImageWidget(imageUrl: data.url!.url)), + child: Hero( + tag: data.url!.url, + child: NetworkImageWidget( + imageUrl: data.url!.url, + ), + ), ), ], ), @@ -230,13 +369,25 @@ class ChatScreen extends StatelessWidget { heroTag: data.id, backgroundColor: AppThemeData.primary300, onPressed: () { - Get.to(FullScreenVideoViewer(heroTag: data.id.toString(), videoUrl: data.url!.url)); + Get.to( + FullScreenVideoViewer( + heroTag: data.id.toString(), + videoUrl: data.url!.url, + ), + ); }, - child: const Icon(Icons.play_arrow, color: Colors.white), + child: const Icon( + Icons.play_arrow, + color: Colors.white, + ), ), const SizedBox(height: 5), Text( - DateFormat('MMM d, yyyy hh:mm aa').format(DateTime.fromMillisecondsSinceEpoch(data.createdAt!.millisecondsSinceEpoch)), + DateFormat('MMM d, yyyy hh:mm aa').format( + DateTime.fromMillisecondsSinceEpoch( + data.createdAt!.millisecondsSinceEpoch, + ), + ), style: const TextStyle(color: Colors.grey, fontSize: 12), ), ], @@ -252,9 +403,14 @@ class ChatScreen extends StatelessWidget { isDefaultAction: false, onPressed: () async { Get.back(); - XFile? image = await controller.imagePicker.pickImage(source: ImageSource.gallery); + XFile? image = await controller.imagePicker.pickImage( + source: ImageSource.gallery, + ); if (image != null) { - Url url = await FireStoreUtils.uploadChatImageToFireStorage(File(image.path), context); + Url url = await FireStoreUtils.uploadChatImageToFireStorage( + File(image.path), + context, + ); controller.sendMessage('', url, '', 'image'); } }, @@ -264,11 +420,22 @@ class ChatScreen extends StatelessWidget { isDefaultAction: false, onPressed: () async { Get.back(); - XFile? galleryVideo = await controller.imagePicker.pickVideo(source: ImageSource.gallery); + XFile? galleryVideo = await controller.imagePicker.pickVideo( + source: ImageSource.gallery, + ); if (galleryVideo != null) { - ChatVideoContainer? videoContainer = await FireStoreUtils.uploadChatVideoToFireStorage(context, File(galleryVideo.path)); + ChatVideoContainer? videoContainer = + await FireStoreUtils.uploadChatVideoToFireStorage( + context, + File(galleryVideo.path), + ); if (videoContainer != null) { - controller.sendMessage('', videoContainer.videoUrl, videoContainer.thumbnailUrl, 'video'); + controller.sendMessage( + '', + videoContainer.videoUrl, + videoContainer.thumbnailUrl, + 'video', + ); } } }, @@ -278,9 +445,14 @@ class ChatScreen extends StatelessWidget { isDestructiveAction: false, onPressed: () async { Get.back(); - XFile? image = await controller.imagePicker.pickImage(source: ImageSource.camera); + XFile? image = await controller.imagePicker.pickImage( + source: ImageSource.camera, + ); if (image != null) { - Url url = await FireStoreUtils.uploadChatImageToFireStorage(File(image.path), context); + Url url = await FireStoreUtils.uploadChatImageToFireStorage( + File(image.path), + context, + ); controller.sendMessage('', url, '', 'image'); } }, diff --git a/lib/screen_ui/multi_vendor_service/chat_screens/driver_inbox_screen.dart b/lib/screen_ui/multi_vendor_service/chat_screens/driver_inbox_screen.dart index 4427f8d..39bf091 100644 --- a/lib/screen_ui/multi_vendor_service/chat_screens/driver_inbox_screen.dart +++ b/lib/screen_ui/multi_vendor_service/chat_screens/driver_inbox_screen.dart @@ -7,8 +7,7 @@ import 'package:customer/themes/responsive.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -25,10 +24,19 @@ class DriverInboxScreen extends StatelessWidget { final isDark = themeController.isDark.value; return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Driver Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Driver Inbox".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: FirestorePagination( //item builder type is compulsory. @@ -40,8 +48,12 @@ class DriverInboxScreen extends StatelessWidget { onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString()); + UserModel? customer = await FireStoreUtils.getUserProfile( + inboxModel.customerId.toString(), + ); + UserModel? restaurantUser = await FireStoreUtils.getUserProfile( + inboxModel.restaurantId.toString(), + ); ShowToastDialog.closeLoader(); Get.to( @@ -62,15 +74,23 @@ class DriverInboxScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: NetworkImageWidget( - imageUrl: inboxModel.restaurantProfileImage.toString(), + imageUrl: + inboxModel.restaurantProfileImage.toString(), fit: BoxFit.cover, height: Responsive.height(6, context), width: Responsive.width(12, context), @@ -87,13 +107,29 @@ class DriverInboxScreen extends StatelessWidget { child: Text( "${inboxModel.restaurantName}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ), Text( - Constant.timestampToDate(inboxModel.createdAt!), + Constant.timestampToDate( + inboxModel.createdAt!, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -101,7 +137,14 @@ class DriverInboxScreen extends StatelessWidget { Text( "${inboxModel.lastMessage}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + ), ), ], ), @@ -116,7 +159,10 @@ class DriverInboxScreen extends StatelessWidget { shrinkWrap: true, onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()), // orderBy is compulsory to enable pagination - query: FirebaseFirestore.instance.collection('chat_driver').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true), + query: FirebaseFirestore.instance + .collection('chat_driver') + .where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()) + .orderBy('createdAt', descending: true), //Change types customerId viewType: ViewType.list, initialLoader: Constant.loader(), diff --git a/lib/screen_ui/multi_vendor_service/chat_screens/restaurant_inbox_screen.dart b/lib/screen_ui/multi_vendor_service/chat_screens/restaurant_inbox_screen.dart index 9f99581..a1d22b5 100644 --- a/lib/screen_ui/multi_vendor_service/chat_screens/restaurant_inbox_screen.dart +++ b/lib/screen_ui/multi_vendor_service/chat_screens/restaurant_inbox_screen.dart @@ -10,8 +10,7 @@ import 'package:customer/widget/firebase_pagination/src/fireStore_pagination.dar import 'package:customer/widget/firebase_pagination/src/models/view_type.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -26,10 +25,19 @@ class RestaurantInboxScreen extends StatelessWidget { final isDark = themeController.isDark.value; return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Store Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Store Inbox".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: FirestorePagination( //item builder type is compulsory. @@ -41,9 +49,15 @@ class RestaurantInboxScreen extends StatelessWidget { onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(restaurantUser!.vendorID.toString()); + UserModel? customer = await FireStoreUtils.getUserProfile( + inboxModel.customerId.toString(), + ); + UserModel? restaurantUser = await FireStoreUtils.getUserProfile( + inboxModel.restaurantId.toString(), + ); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + restaurantUser!.vendorID.toString(), + ); ShowToastDialog.closeLoader(); Get.to( @@ -64,15 +78,23 @@ class RestaurantInboxScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: NetworkImageWidget( - imageUrl: inboxModel.restaurantProfileImage.toString(), + imageUrl: + inboxModel.restaurantProfileImage.toString(), fit: BoxFit.cover, height: Responsive.height(6, context), width: Responsive.width(12, context), @@ -89,13 +111,29 @@ class RestaurantInboxScreen extends StatelessWidget { child: Text( "${inboxModel.restaurantName}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ), Text( - Constant.timestampToDate(inboxModel.createdAt!), + Constant.timestampToDate( + inboxModel.createdAt!, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -103,7 +141,14 @@ class RestaurantInboxScreen extends StatelessWidget { Text( "${inboxModel.lastMessage}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + ), ), ], ), @@ -118,7 +163,10 @@ class RestaurantInboxScreen extends StatelessWidget { shrinkWrap: true, onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()), // orderBy is compulsory to enable pagination - query: FirebaseFirestore.instance.collection('chat_store').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true), + query: FirebaseFirestore.instance + .collection('chat_store') + .where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()) + .orderBy('createdAt', descending: true), //Change types customerId viewType: ViewType.list, initialLoader: Constant.loader(), diff --git a/lib/screen_ui/multi_vendor_service/dash_board_screens/dash_board_screen.dart b/lib/screen_ui/multi_vendor_service/dash_board_screens/dash_board_screen.dart index 90c1480..0421c23 100644 --- a/lib/screen_ui/multi_vendor_service/dash_board_screens/dash_board_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dash_board_screens/dash_board_screen.dart @@ -4,8 +4,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; class DashBoardScreen extends StatelessWidget { @@ -26,12 +25,19 @@ class DashBoardScreen extends StatelessWidget { showUnselectedLabels: true, showSelectedLabels: true, selectedFontSize: 12, - selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), - unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), + selectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), + unselectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), currentIndex: controller.selectedIndex.value, - backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - selectedItemColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - unselectedItemColor: isDark ? AppThemeData.grey300 : AppThemeData.grey600, + backgroundColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + selectedItemColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, + unselectedItemColor: + isDark ? AppThemeData.grey300 : AppThemeData.grey600, onTap: (int index) { if (index == 0) { Get.put(DashBoardController()); @@ -41,17 +47,71 @@ class DashBoardScreen extends StatelessWidget { items: Constant.walletSetting == false ? [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_orders.svg", label: 'Orders'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_orders.svg", + label: 'Orders'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ] : [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_wallet.svg", label: 'Wallet'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_orders.svg", label: 'Orders'.tr(), controller: controller), - navigationBarItem(isDark, index: 4, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_wallet.svg", + label: 'Wallet'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_orders.svg", + label: 'Orders'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 4, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ], ), ); @@ -60,7 +120,13 @@ class DashBoardScreen extends StatelessWidget { }); } - BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required DashBoardController controller}) { + BottomNavigationBarItem navigationBarItem( + isDark, { + required int index, + required String label, + required String assetIcon, + required DashBoardController controller, + }) { return BottomNavigationBarItem( icon: Padding( padding: const EdgeInsets.symmetric(vertical: 5), diff --git a/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_details.dart b/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_details.dart index 8bb2ec2..b19398c 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_details.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_details.dart @@ -4,7 +4,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:url_launcher/url_launcher.dart'; import '../../../controllers/theme_controller.dart'; @@ -23,10 +23,16 @@ class DineInBookingDetails extends StatelessWidget { appBar: AppBar( centerTitle: false, titleSpacing: 0, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, title: Text( "Dine in Bookings".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), body: @@ -45,25 +51,55 @@ class DineInBookingDetails extends StatelessWidget { children: [ Text( "${'Order'.tr()} ${Constant.orderId(orderId: controller.bookingModel.value.id.toString())}", - style: TextStyle(fontSize: 18, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), Text( "${controller.bookingModel.value.totalGuest} ${'Peoples'.tr()}", - style: TextStyle(fontSize: 14, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ], ), ), Container( decoration: ShapeDecoration( - color: Constant.statusColor(status: controller.bookingModel.value.status), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + color: Constant.statusColor( + status: controller.bookingModel.value.status, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 6, + ), child: Text( "${controller.bookingModel.value.status}", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), ), @@ -71,7 +107,15 @@ class DineInBookingDetails extends StatelessWidget { ), const SizedBox(height: 20), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -79,19 +123,47 @@ class DineInBookingDetails extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_building.svg"), + SvgPicture.asset( + "assets/icons/ic_building.svg", + ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.bookingModel.value.vendor!.title.toString(), - style: TextStyle(fontSize: 18, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + controller + .bookingModel + .value + .vendor! + .title + .toString(), + style: TextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), Text( - controller.bookingModel.value.vendor!.location.toString(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + controller + .bookingModel + .value + .vendor! + .location + .toString(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ], ), @@ -107,9 +179,23 @@ class DineInBookingDetails extends StatelessWidget { onTap: () { launchUrl( Constant.createCoordinatesUrl( - controller.bookingModel.value.vendor!.latitude ?? 0.0, - controller.bookingModel.value.vendor!.longitude ?? 0.0, - controller.bookingModel.value.vendor!.title, + controller + .bookingModel + .value + .vendor! + .latitude ?? + 0.0, + controller + .bookingModel + .value + .vendor! + .longitude ?? + 0.0, + controller + .bookingModel + .value + .vendor! + .title, ), ); }, @@ -117,19 +203,44 @@ class DineInBookingDetails extends StatelessWidget { "View in Map".tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, decoration: TextDecoration.underline, - decorationColor: AppThemeData.primary300, + decorationColor: + AppThemeData.primary300, ), ), ), - const Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: SizedBox(height: 16, child: VerticalDivider(width: 1))), + const Padding( + padding: EdgeInsets.symmetric( + horizontal: 16, + ), + child: SizedBox( + height: 16, + child: VerticalDivider(width: 1), + ), + ), InkWell( onTap: () { - if (controller.bookingModel.value.vendor!.phonenumber!.isNotEmpty) { - final Uri launchUri = Uri(scheme: 'tel', path: controller.bookingModel.value.vendor!.phonenumber); + if (controller + .bookingModel + .value + .vendor! + .phonenumber! + .isNotEmpty) { + final Uri launchUri = Uri( + scheme: 'tel', + path: + controller + .bookingModel + .value + .vendor! + .phonenumber, + ); launchUrl(launchUri); } }, @@ -137,11 +248,15 @@ class DineInBookingDetails extends StatelessWidget { "Call Now".tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, decoration: TextDecoration.underline, - decorationColor: AppThemeData.primary300, + decorationColor: + AppThemeData.primary300, ), ), ), @@ -156,11 +271,26 @@ class DineInBookingDetails extends StatelessWidget { Text( "Booking Details".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 5), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -171,14 +301,28 @@ class DineInBookingDetails extends StatelessWidget { Expanded( child: Text( "Name".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Expanded( child: Text( "${controller.bookingModel.value.guestFirstName} ${controller.bookingModel.value.guestLastName}", textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], @@ -190,14 +334,28 @@ class DineInBookingDetails extends StatelessWidget { Expanded( child: Text( "Phone number".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Expanded( child: Text( "${controller.bookingModel.value.guestPhone}", textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], @@ -209,14 +367,30 @@ class DineInBookingDetails extends StatelessWidget { Expanded( child: Text( "Date and Time".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Expanded( child: Text( - Constant.timestampToDateTime(controller.bookingModel.value.date!), + Constant.timestampToDateTime( + controller.bookingModel.value.date!, + ), textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], @@ -228,14 +402,28 @@ class DineInBookingDetails extends StatelessWidget { Expanded( child: Text( "Guest".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Expanded( child: Text( "${controller.bookingModel.value.totalGuest}", textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], @@ -247,14 +435,28 @@ class DineInBookingDetails extends StatelessWidget { Expanded( child: Text( "Discount".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Expanded( child: Text( "${controller.bookingModel.value.discount} %", textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_screen.dart index 1bbeb1d..85e714c 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_booking/dine_in_booking_screen.dart @@ -6,7 +6,7 @@ import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/app_them_data.dart'; import '../../../widget/my_separator.dart'; @@ -26,10 +26,16 @@ class DineInBookingScreen extends StatelessWidget { appBar: AppBar( centerTitle: false, titleSpacing: 0, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, title: Text( "Dine in Bookings".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), body: @@ -40,7 +46,15 @@ class DineInBookingScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(120), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( @@ -54,16 +68,28 @@ class DineInBookingScreen extends StatelessWidget { decoration: controller.isFeature.value == false ? null - : ShapeDecoration(color: AppThemeData.primary300, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + : ShapeDecoration( + color: AppThemeData.primary300, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Text( "Upcoming".tr(), textAlign: TextAlign.center, style: TextStyle( fontFamily: AppThemeData.semiBold, color: - controller.isFeature.value == false + controller.isFeature.value == + false ? isDark ? AppThemeData.grey400 : AppThemeData.grey500 @@ -85,16 +111,28 @@ class DineInBookingScreen extends StatelessWidget { decoration: controller.isFeature.value == true ? null - : ShapeDecoration(color: AppThemeData.primary300, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + : ShapeDecoration( + color: AppThemeData.primary300, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Text( "History".tr(), textAlign: TextAlign.center, style: TextStyle( fontFamily: AppThemeData.semiBold, color: - controller.isFeature.value == true + controller.isFeature.value == + true ? isDark ? AppThemeData.grey400 : AppThemeData.grey500 @@ -119,26 +157,45 @@ class DineInBookingScreen extends StatelessWidget { child: controller.isFeature.value ? controller.featureList.isEmpty - ? Constant.showEmptyView(message: "Upcoming Booking not found.".tr()) + ? Constant.showEmptyView( + message: + "Upcoming Booking not found.".tr(), + ) : ListView.builder( shrinkWrap: true, padding: EdgeInsets.zero, scrollDirection: Axis.vertical, - itemCount: controller.featureList.length, - itemBuilder: (BuildContext context, int index) { - DineInBookingModel dineBookingModel = controller.featureList[index]; - return itemView(isDark, context, dineBookingModel); + itemCount: + controller.featureList.length, + itemBuilder: ( + BuildContext context, + int index, + ) { + DineInBookingModel dineBookingModel = + controller.featureList[index]; + return itemView( + isDark, + context, + dineBookingModel, + ); }, ) : controller.historyList.isEmpty - ? Constant.showEmptyView(message: "History not found.".tr()) + ? Constant.showEmptyView( + message: "History not found.".tr(), + ) : ListView.builder( itemCount: controller.historyList.length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - DineInBookingModel dineBookingModel = controller.historyList[index]; - return itemView(isDark, context, dineBookingModel); + DineInBookingModel dineBookingModel = + controller.historyList[index]; + return itemView( + isDark, + context, + dineBookingModel, + ); }, ), ), @@ -150,15 +207,27 @@ class DineInBookingScreen extends StatelessWidget { ); } - InkWell itemView(isDark, BuildContext context, DineInBookingModel orderModel) { + InkWell itemView( + isDark, + BuildContext context, + DineInBookingModel orderModel, + ) { return InkWell( onTap: () { - Get.to(const DineInBookingDetails(), arguments: {"bookingModel": orderModel}); + Get.to( + const DineInBookingDetails(), + arguments: {"bookingModel": orderModel}, + ); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -169,12 +238,24 @@ class DineInBookingScreen extends StatelessWidget { borderRadius: const BorderRadius.all(Radius.circular(16)), child: Stack( children: [ - NetworkImageWidget(imageUrl: orderModel.vendor!.photo.toString(), fit: BoxFit.cover, height: Responsive.height(10, context), width: Responsive.width(20, context)), + NetworkImageWidget( + imageUrl: orderModel.vendor!.photo.toString(), + fit: BoxFit.cover, + height: Responsive.height(10, context), + width: Responsive.width(20, context), + ), Container( height: Responsive.height(10, context), width: Responsive.width(20, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, 1.00), end: const Alignment(0, -1), colors: [Colors.black.withOpacity(0), AppThemeData.grey900]), + gradient: LinearGradient( + begin: const Alignment(0.00, 1.00), + end: const Alignment(0, -1), + colors: [ + Colors.black.withOpacity(0), + AppThemeData.grey900, + ], + ), ), ), ], @@ -188,33 +269,79 @@ class DineInBookingScreen extends StatelessWidget { Text( orderModel.status.toString(), textAlign: TextAlign.right, - style: TextStyle(color: Constant.statusColor(status: orderModel.status.toString()), fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500, fontSize: 12), + style: TextStyle( + color: Constant.statusColor( + status: orderModel.status.toString(), + ), + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + fontSize: 12, + ), ), const SizedBox(height: 5), Text( orderModel.vendor!.title.toString(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w400), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 5), Text( Constant.timestampToDateTime(orderModel.createdAt!), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ], ), ), ], ), - Padding(padding: const EdgeInsets.symmetric(vertical: 14), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 14), + child: MySeparator( + color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + ), + ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: Text("Name".tr(), style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400))), + Expanded( + child: Text( + "Name".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), + ), + ), Expanded( child: Text( "${orderModel.guestFirstName} ${orderModel.guestLastName}", textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], @@ -224,18 +351,40 @@ class DineInBookingScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: Text("Guest Number".tr(), style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400)), + child: Text( + "Guest Number".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), + ), ), Expanded( child: Text( orderModel.totalGuest.toString(), textAlign: TextAlign.end, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ), ], ), - Padding(padding: const EdgeInsets.symmetric(vertical: 14), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 14), + child: MySeparator( + color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + ), + ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -244,7 +393,14 @@ class DineInBookingScreen extends StatelessWidget { Expanded( child: Text( orderModel.vendor!.location.toString(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/dine_in_screeen/book_table_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_screeen/book_table_screen.dart index 96da285..a8dcaf3 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_screeen/book_table_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_screeen/book_table_screen.dart @@ -8,7 +8,7 @@ import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../../../controllers/theme_controller.dart'; @@ -27,8 +27,17 @@ class BookTableScreen extends StatelessWidget { appBar: AppBar( centerTitle: false, titleSpacing: 0, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - title: Text("Book Table".tr(), style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500)), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + title: Text( + "Book Table".tr(), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), + ), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -37,25 +46,55 @@ class BookTableScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), child: Row( children: [ Expanded( child: Text( "Numbers of Guests".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), Container( height: Responsive.height(4, context), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(200), side: BorderSide(color: isDark ? AppThemeData.grey600 : AppThemeData.grey300)), + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(200), + side: BorderSide( + color: + isDark + ? AppThemeData.grey600 + : AppThemeData.grey300, + ), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), + padding: const EdgeInsets.symmetric( + horizontal: 5, + ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -69,7 +108,9 @@ class BookTableScreen extends StatelessWidget { child: const Icon(Icons.remove), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Text( controller.noOfQuantity.toString(), textAlign: TextAlign.start, @@ -79,7 +120,10 @@ class BookTableScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), @@ -87,7 +131,10 @@ class BookTableScreen extends StatelessWidget { onTap: () { controller.noOfQuantity.value += 1; }, - child: Icon(Icons.add, color: AppThemeData.primary300), + child: Icon( + Icons.add, + color: AppThemeData.primary300, + ), ), ], ), @@ -99,7 +146,13 @@ class BookTableScreen extends StatelessWidget { ), const SizedBox(height: 10), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -107,12 +160,22 @@ class BookTableScreen extends StatelessWidget { children: [ Text( "When are you visiting?".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), SizedBox( height: 120, child: ListView.builder( - padding: const EdgeInsets.symmetric(horizontal: 8), + padding: const EdgeInsets.symmetric( + horizontal: 8, + ), physics: const BouncingScrollPhysics(), itemCount: controller.dateList.length, scrollDirection: Axis.horizontal, @@ -120,11 +183,17 @@ class BookTableScreen extends StatelessWidget { return Stack( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 2.0, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 2.0, + vertical: 8, + ), child: GestureDetector( onTap: () { - controller.selectedDate.value = controller.dateList[index].date; - controller.timeSet(controller.dateList[index].date); + controller.selectedDate.value = + controller.dateList[index].date; + controller.timeSet( + controller.dateList[index].date, + ); }, child: Obx( () => Container( @@ -135,41 +204,93 @@ class BookTableScreen extends StatelessWidget { side: BorderSide( width: 1, color: - controller.selectedDate.value == controller.dateList[index].date - ? AppThemeData.primary300 + controller + .selectedDate + .value == + controller + .dateList[index] + .date + ? AppThemeData + .primary300 : isDark ? AppThemeData.grey800 - : AppThemeData.grey100, + : AppThemeData + .grey100, ), - borderRadius: BorderRadius.circular(8), + borderRadius: + BorderRadius.circular(8), ), ), child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all( + 8.0, + ), child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Text( - Constant.calculateDifference(controller.dateList[index].date.toDate()) == 0 + Constant.calculateDifference( + controller + .dateList[index] + .date + .toDate(), + ) == + 0 ? "Today".tr() - : Constant.calculateDifference(controller.dateList[index].date.toDate()) == 1 + : Constant.calculateDifference( + controller + .dateList[index] + .date + .toDate(), + ) == + 1 ? "Tomorrow".tr() - : DateFormat('EEE').format(controller.dateList[index].date.toDate()), + : DateFormat( + 'EEE', + ).format( + controller + .dateList[index] + .date + .toDate(), + ), style: TextStyle( fontSize: 12, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + fontFamily: + AppThemeData.regular, + fontWeight: + FontWeight.w500, ), ), Text( - DateFormat('d MMM').format(controller.dateList[index].date.toDate()).toString(), + DateFormat('d MMM') + .format( + controller + .dateList[index] + .date + .toDate(), + ) + .toString(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -185,8 +306,10 @@ class BookTableScreen extends StatelessWidget { right: 0, child: Center( child: RoundedButtonFill( - borderRadius: 10.r, - title: "${controller.dateList[index].discountPer}%".tr(), + borderRadius: 10.r, + title: + "${controller.dateList[index].discountPer}%" + .tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, width: 12, @@ -203,30 +326,69 @@ class BookTableScreen extends StatelessWidget { const SizedBox(height: 10), Text( "Select time slot and scroll to see offers".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( decoration: ShapeDecoration( - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: isDark ? AppThemeData.grey600 : AppThemeData.grey300), borderRadius: BorderRadius.circular(12)), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey600 + : AppThemeData.grey300, + ), + borderRadius: BorderRadius.circular(12), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 5, + vertical: 5, + ), child: Wrap( spacing: 5.0, children: [ ...controller.timeSlotList.map( (timeSlotList) => InputChip( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), side: BorderSide.none, - backgroundColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + backgroundColor: + isDark + ? AppThemeData.grey800 + : AppThemeData.grey100, selectedColor: AppThemeData.primary300, - labelStyle: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + labelStyle: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), label: Text( - DateFormat('hh:mm a').format(timeSlotList.time!), + DateFormat( + 'hh:mm a', + ).format(timeSlotList.time!), style: TextStyle( color: - controller.selectedTimeSlot.value == DateFormat('hh:mm a').format(timeSlotList.time!) + controller + .selectedTimeSlot + .value == + DateFormat( + 'hh:mm a', + ).format( + timeSlotList.time!, + ) ? AppThemeData.grey50 : isDark ? AppThemeData.grey400 @@ -236,11 +398,22 @@ class BookTableScreen extends StatelessWidget { ), ), showCheckmark: false, - selected: controller.selectedTimeSlot.value == DateFormat('hh:mm a').format(timeSlotList.time!), + selected: + controller.selectedTimeSlot.value == + DateFormat( + 'hh:mm a', + ).format(timeSlotList.time!), onSelected: (value) { - controller.selectedTimeSlot.value = DateFormat('hh:mm a').format(timeSlotList.time!); - controller.selectedTimeDiscount.value = timeSlotList.discountPer!; - controller.selectedTimeDiscountType.value = timeSlotList.discountType!; + controller + .selectedTimeSlot + .value = DateFormat( + 'hh:mm a', + ).format(timeSlotList.time!); + controller.selectedTimeDiscount.value = + timeSlotList.discountPer!; + controller + .selectedTimeDiscountType + .value = timeSlotList.discountType!; }, ), ), @@ -258,55 +431,120 @@ class BookTableScreen extends StatelessWidget { Expanded( child: Text( "Special Occasion".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), ), InkWell( onTap: () { controller.selectedOccasion.value = ""; }, - child: Text("Clear".tr(), style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500)), + child: Text( + "Clear".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), + ), ), ], ), const SizedBox(height: 10), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - for (int i = 0; i < controller.occasionList[i].length; i++) + for ( + int i = 0; + i < controller.occasionList[i].length; + i++ + ) ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0), - visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + contentPadding: const EdgeInsets.symmetric( + horizontal: 0.0, + vertical: 0.0, + ), + visualDensity: const VisualDensity( + horizontal: 0, + vertical: -4, + ), dense: true, title: Text( //'${controller.occasionList[i]}'.tr(), - controller.getLocalizedOccasion(controller.occasionList[i]), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + controller.getLocalizedOccasion( + controller.occasionList[i], + ), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), leading: Radio( - visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + visualDensity: const VisualDensity( + horizontal: 0, + vertical: -4, + ), value: controller.occasionList[i], groupValue: controller.selectedOccasion.value, activeColor: AppThemeData.primary300, onChanged: (value) { - controller.selectedOccasion.value = controller.occasionList[i]; + controller.selectedOccasion.value = + controller.occasionList[i]; }, ), ), ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0), - visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + contentPadding: const EdgeInsets.symmetric( + horizontal: 0.0, + vertical: 0.0, + ), + visualDensity: const VisualDensity( + horizontal: 0, + vertical: -4, + ), dense: true, title: Text( 'Is this your first visit?'.tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), leading: Checkbox( - visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + visualDensity: const VisualDensity( + horizontal: 0, + vertical: -4, + ), value: controller.firstVisit.value, activeColor: AppThemeData.primary300, onChanged: (value) { @@ -321,22 +559,44 @@ class BookTableScreen extends StatelessWidget { const SizedBox(height: 10), Text( "Personal Details".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ ClipOval( child: NetworkImageWidget( - imageUrl: Constant.userModel!.profilePictureURL.toString(), + imageUrl: + Constant.userModel!.profilePictureURL + .toString(), width: 50, height: 50, - errorWidget: Image.asset(Constant.userPlaceHolder, fit: BoxFit.cover, width: 50, height: 50), + errorWidget: Image.asset( + Constant.userPlaceHolder, + fit: BoxFit.cover, + width: 50, + height: 50, + ), ), ), const SizedBox(width: 10), @@ -345,11 +605,27 @@ class BookTableScreen extends StatelessWidget { children: [ Text( Constant.userModel!.fullName(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( "${Constant.userModel!.email}", - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ], ), @@ -360,10 +636,20 @@ class BookTableScreen extends StatelessWidget { const SizedBox(height: 10), Text( "Additional Requests".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), - TextFieldWidget(controller: controller.additionRequestController.value, hintText: 'Add message here....'.tr(), maxLine: 5), + TextFieldWidget( + controller: controller.additionRequestController.value, + hintText: 'Add message here....'.tr(), + maxLine: 5, + ), const SizedBox(height: 20), ], ), @@ -375,7 +661,7 @@ class BookTableScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(bottom: 20), child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Book Now".tr(), height: 5.5, color: AppThemeData.primary300, diff --git a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_details_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_details_screen.dart index 19c048e..3912671 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_details_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_details_screen.dart @@ -13,7 +13,7 @@ import '../restaurant_details_screen/restaurant_details_screen.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:url_launcher/url_launcher.dart'; import '../review_list_screen/review_list_screen.dart'; import 'book_table_screen.dart'; @@ -30,7 +30,10 @@ class DineInDetailsScreen extends StatelessWidget { builder: (controller) { return Scaffold( body: NestedScrollView( - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + headerSliverBuilder: ( + BuildContext context, + bool innerBoxIsScrolled, + ) { return [ SliverAppBar( expandedHeight: Responsive.height(30, context), @@ -44,26 +47,66 @@ class DineInDetailsScreen extends StatelessWidget { onTap: () { Get.back(); }, - child: Icon(Icons.arrow_back, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + child: Icon( + Icons.arrow_back, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), const Expanded(child: SizedBox()), InkWell( onTap: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == controller.vendorModel.value.id).isNotEmpty) { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: controller.vendorModel.value.id, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.removeWhere((item) => item.restaurantId == controller.vendorModel.value.id); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); + if (controller.favouriteList + .where( + (p0) => + p0.restaurantId == + controller.vendorModel.value.id, + ) + .isNotEmpty) { + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: controller.vendorModel.value.id, + userId: FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.removeWhere( + (item) => + item.restaurantId == + controller.vendorModel.value.id, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: controller.vendorModel.value.id, userId: FireStoreUtils.getCurrentUid()); + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: controller.vendorModel.value.id, + userId: FireStoreUtils.getCurrentUid(), + ); controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } }, child: Obx( () => - controller.favouriteList.where((p0) => p0.restaurantId == controller.vendorModel.value.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg", colorFilter: const ColorFilter.mode(AppThemeData.grey50, BlendMode.srcIn)) - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteList + .where( + (p0) => + p0.restaurantId == + controller.vendorModel.value.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + colorFilter: const ColorFilter.mode( + AppThemeData.grey50, + BlendMode.srcIn, + ), + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), ], @@ -71,18 +114,28 @@ class DineInDetailsScreen extends StatelessWidget { flexibleSpace: FlexibleSpaceBar( background: Stack( children: [ - controller.vendorModel.value.photos == null || controller.vendorModel.value.photos!.isEmpty + controller.vendorModel.value.photos == null || + controller.vendorModel.value.photos!.isEmpty ? Stack( children: [ NetworkImageWidget( - imageUrl: controller.vendorModel.value.photo.toString(), + imageUrl: + controller.vendorModel.value.photo + .toString(), fit: BoxFit.cover, width: Responsive.width(100, context), height: Responsive.height(40, context), ), Container( decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), Colors.black]), + gradient: LinearGradient( + begin: const Alignment(0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + Colors.black, + ], + ), ), ), ], @@ -91,20 +144,34 @@ class DineInDetailsScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), controller: controller.pageController.value, scrollDirection: Axis.horizontal, - itemCount: controller.vendorModel.value.photos!.length, + itemCount: + controller.vendorModel.value.photos!.length, padEnds: false, pageSnapping: true, onPageChanged: (value) { controller.currentPage.value = value; }, itemBuilder: (BuildContext context, int index) { - String image = controller.vendorModel.value.photos![index]; + String image = + controller.vendorModel.value.photos![index]; return Stack( children: [ - NetworkImageWidget(imageUrl: image.toString(), fit: BoxFit.cover, width: Responsive.width(100, context), height: Responsive.height(40, context)), + NetworkImageWidget( + imageUrl: image.toString(), + fit: BoxFit.cover, + width: Responsive.width(100, context), + height: Responsive.height(40, context), + ), Container( decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), Colors.black]), + gradient: LinearGradient( + begin: const Alignment(0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + Colors.black, + ], + ), ), ), ], @@ -118,17 +185,26 @@ class DineInDetailsScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, - children: List.generate(controller.vendorModel.value.photos!.length, (index) { - return Obx( - () => Container( - margin: const EdgeInsets.only(right: 5), - alignment: Alignment.centerLeft, - height: 9, - width: 9, - decoration: BoxDecoration(shape: BoxShape.circle, color: controller.currentPage.value == index ? AppThemeData.primary300 : AppThemeData.grey300), - ), - ); - }), + children: List.generate( + controller.vendorModel.value.photos!.length, + (index) { + return Obx( + () => Container( + margin: const EdgeInsets.only(right: 5), + alignment: Alignment.centerLeft, + height: 9, + width: 9, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + controller.currentPage.value == index + ? AppThemeData.primary300 + : AppThemeData.grey300, + ), + ), + ); + }, + ), ), ), ], @@ -149,38 +225,64 @@ class DineInDetailsScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.vendorModel.value.title.toString(), + controller.vendorModel.value.title + .toString(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( fontSize: 22, overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), SizedBox( - width: Responsive.width(78, context), + width: Responsive.width( + 78, + context, + ), child: Text( - controller.vendorModel.value.location.toString(), + controller + .vendorModel + .value + .location + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, color: isDark ? AppThemeData.grey400 : AppThemeData.grey400), + style: TextStyle( + fontFamily: + AppThemeData.medium, + fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey400, + ), ), ), ], @@ -190,21 +292,59 @@ class DineInDetailsScreen extends StatelessWidget { children: [ Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(120), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + padding: + const EdgeInsets.symmetric( + horizontal: 12, + vertical: 4, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( Constant.calculateReview( - reviewCount: controller.vendorModel.value.reviewsCount!.toStringAsFixed(0), - reviewSum: controller.vendorModel.value.reviewsSum.toString(), + reviewCount: controller + .vendorModel + .value + .reviewsCount! + .toStringAsFixed(0), + reviewSum: + controller + .vendorModel + .value + .reviewsSum + .toString(), + ), + style: TextStyle( + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), ), ], ), @@ -213,11 +353,28 @@ class DineInDetailsScreen extends StatelessWidget { const SizedBox(height: 5), InkWell( onTap: () { - Get.to(const ReviewListScreen(), arguments: {"vendorModel": controller.vendorModel.value}); + Get.to( + const ReviewListScreen(), + arguments: { + "vendorModel": + controller + .vendorModel + .value, + }, + ); }, child: Text( "${controller.vendorModel.value.reviewsCount} ${'Ratings'.tr()}", - style: TextStyle(decoration: TextDecoration.underline, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular), + style: TextStyle( + decoration: + TextDecoration.underline, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + fontFamily: + AppThemeData.regular, + ), ), ), ], @@ -227,7 +384,9 @@ class DineInDetailsScreen extends StatelessWidget { Row( children: [ Text( - controller.isOpen.value ? "Open".tr() : "Close".tr(), + controller.isOpen.value + ? "Open".tr() + : "Close".tr(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( @@ -235,13 +394,31 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: controller.isOpen.value ? AppThemeData.success400 : AppThemeData.danger300, + color: + controller.isOpen.value + ? AppThemeData.success400 + : AppThemeData.danger300, + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Icon( + Icons.circle, + size: 5, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, ), ), - Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child: Icon(Icons.circle, size: 5, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500)), InkWell( onTap: () { - timeShowBottomSheet(context, controller); + timeShowBottomSheet( + context, + controller, + ); }, child: Text( "View Timings".tr(), @@ -249,18 +426,36 @@ class DineInDetailsScreen extends StatelessWidget { maxLines: 1, style: TextStyle( fontSize: 14, - decoration: TextDecoration.underline, - decorationColor: AppThemeData.ecommerce300, + decoration: + TextDecoration.underline, + decorationColor: + AppThemeData.ecommerce300, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, + color: + isDark + ? AppThemeData.ecommerce300 + : AppThemeData.ecommerce300, ), ), ), - Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child: Icon(Icons.circle, size: 5, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500)), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Icon( + Icons.circle, + size: 5, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), + ), Text( - "${Constant.amountShow(amount: controller.vendorModel.value.restaurantCost)} ${'for two'.tr()}".tr(), + "${Constant.amountShow(amount: controller.vendorModel.value.restaurantCost)} ${'for two'.tr()}" + .tr(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( @@ -268,13 +463,17 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, ), ), ], ), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ const SizedBox(height: 20), Text( @@ -286,62 +485,123 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), InkWell( onTap: () { if (Constant.userModel == null) { - ShowToastDialog.showToast("Please log in to the application. You are not logged in.".tr()); + ShowToastDialog.showToast( + "Please log in to the application. You are not logged in." + .tr(), + ); } else { - Get.to(const BookTableScreen(), arguments: {"vendorModel": controller.vendorModel.value}); + Get.to( + const BookTableScreen(), + arguments: { + "vendorModel": + controller + .vendorModel + .value, + }, + ); } }, child: Container( height: 80, clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), - borderRadius: BorderRadius.circular(16), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + ), + borderRadius: + BorderRadius.circular(16), ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), + ), + child: Image.asset( + "assets/images/ic_table.gif", ), - child: Image.asset("assets/images/ic_table.gif"), ), const SizedBox(width: 10), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( "Table Booking".tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), Text( - "Quick Conformations".tr(), + "Quick Conformations" + .tr(), style: TextStyle( fontSize: 12, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w500, ), ), ], @@ -356,52 +616,109 @@ class DineInDetailsScreen extends StatelessWidget { const SizedBox(height: 10), InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": controller.vendorModel.value}); + Get.to( + const RestaurantDetailsScreen(), + arguments: { + "vendorModel": + controller.vendorModel.value, + }, + ); }, child: Container( height: 80, clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), - borderRadius: BorderRadius.circular(16), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + ), + borderRadius: + BorderRadius.circular(16), ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all(4), + child: Image.asset( + "assets/images/food_delivery.gif", + ), ), - child: Padding(padding: const EdgeInsets.all(4), child: Image.asset("assets/images/food_delivery.gif")), ), const SizedBox(width: 10), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - "Available food delivery".tr(), + "Available food delivery" + .tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), Text( "in 30-45 mins.".tr(), style: TextStyle( fontSize: 12, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w500, ), ), ], @@ -415,10 +732,20 @@ class DineInDetailsScreen extends StatelessWidget { ), ], ), - controller.vendorModel.value.restaurantMenuPhotos == null || controller.vendorModel.value.restaurantMenuPhotos!.isEmpty + controller + .vendorModel + .value + .restaurantMenuPhotos == + null || + controller + .vendorModel + .value + .restaurantMenuPhotos! + .isEmpty ? const SizedBox() : Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ const SizedBox(height: 20), Text( @@ -430,28 +757,65 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), SizedBox( - height: Responsive.height(12, context), + height: Responsive.height( + 12, + context, + ), child: ListView.builder( - itemCount: controller.vendorModel.value.restaurantMenuPhotos!.length, + itemCount: + controller + .vendorModel + .value + .restaurantMenuPhotos! + .length, scrollDirection: Axis.horizontal, padding: EdgeInsets.zero, itemBuilder: (context, index) { return InkWell( onTap: () { - Get.to(FullScreenImageViewer(imageUrl: controller.vendorModel.value.restaurantMenuPhotos![index])); + Get.to( + FullScreenImageViewer( + imageUrl: + controller + .vendorModel + .value + .restaurantMenuPhotos![index], + ), + ); }, child: Padding( - padding: const EdgeInsets.all(6.0), + padding: + const EdgeInsets.all( + 6.0, + ), child: ClipRRect( - borderRadius: BorderRadius.circular(10), + borderRadius: + BorderRadius.circular( + 10, + ), child: NetworkImageWidget( - imageUrl: controller.vendorModel.value.restaurantMenuPhotos![index], - height: Responsive.height(12, context), - width: Responsive.height(12, context), + imageUrl: + controller + .vendorModel + .value + .restaurantMenuPhotos![index], + height: + Responsive.height( + 12, + context, + ), + width: + Responsive.height( + 12, + context, + ), fit: BoxFit.fill, ), ), @@ -464,7 +828,8 @@ class DineInDetailsScreen extends StatelessWidget { ), const SizedBox(height: 20), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Location, Timing & Costs".tr(), @@ -475,36 +840,64 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 20), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_location.svg"), + SvgPicture.asset( + "assets/icons/ic_location.svg", + ), const SizedBox(width: 14), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.vendorModel.value.location.toString(), + controller + .vendorModel + .value + .location + .toString(), textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.regular, + fontFamily: + AppThemeData.regular, fontWeight: FontWeight.w400, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, ), ), InkWell( onTap: () { launchUrl( Constant.createCoordinatesUrl( - controller.vendorModel.value.latitude ?? 0.0, - controller.vendorModel.value.longitude ?? 0.0, - controller.vendorModel.value.title, + controller + .vendorModel + .value + .latitude ?? + 0.0, + controller + .vendorModel + .value + .longitude ?? + 0.0, + controller + .vendorModel + .value + .title, ), ); }, @@ -513,9 +906,16 @@ class DineInDetailsScreen extends StatelessWidget { textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, ), ), ), @@ -526,21 +926,31 @@ class DineInDetailsScreen extends StatelessWidget { ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - SvgPicture.asset("assets/icons/ic_alarm_clock.svg", height: 20), + SvgPicture.asset( + "assets/icons/ic_alarm_clock.svg", + height: 20, + ), const SizedBox(width: 14), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Timing".tr(), textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.regular, + fontFamily: + AppThemeData.regular, fontWeight: FontWeight.w400, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, ), ), InkWell( @@ -550,9 +960,15 @@ class DineInDetailsScreen extends StatelessWidget { textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, ), ), ), @@ -562,25 +978,41 @@ class DineInDetailsScreen extends StatelessWidget { ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - Constant.currencyModel!.symbol.toString(), + Constant.currencyModel!.symbol + .toString(), textAlign: TextAlign.center, - style: TextStyle(fontSize: 24, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w400, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontSize: 24, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), const SizedBox(width: 20), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Cost for Two".tr(), textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.regular, + fontFamily: + AppThemeData.regular, fontWeight: FontWeight.w400, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, ), ), Text( @@ -588,9 +1020,15 @@ class DineInDetailsScreen extends StatelessWidget { textAlign: TextAlign.start, style: TextStyle( fontSize: 16, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, ), ), ], @@ -601,7 +1039,8 @@ class DineInDetailsScreen extends StatelessWidget { ), const SizedBox(height: 20), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Cuisines".tr(), @@ -612,7 +1051,10 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), @@ -621,10 +1063,21 @@ class DineInDetailsScreen extends StatelessWidget { children: [ ...controller.tags.map( (tag) => FilterChip( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(30), + ), side: BorderSide.none, - backgroundColor: isDark ? AppThemeData.grey700 : AppThemeData.grey200, - labelStyle: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + backgroundColor: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + labelStyle: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), label: Text("$tag"), onSelected: (bool value) {}, ), @@ -646,12 +1099,17 @@ class DineInDetailsScreen extends StatelessWidget { ); } - Future timeShowBottomSheet(BuildContext context, DineInRestaurantDetailsController productModel) { + Future timeShowBottomSheet( + BuildContext context, + DineInRestaurantDetailsController productModel, + ) { return showModalBottomSheet( context: context, isScrollControlled: true, isDismissible: true, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), clipBehavior: Clip.antiAliasWithSaveLayer, builder: (context) => FractionallySizedBox( @@ -661,7 +1119,8 @@ class DineInDetailsScreen extends StatelessWidget { final themeController = Get.find(); final isDark = themeController.isDark.value; return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -673,7 +1132,15 @@ class DineInDetailsScreen extends StatelessWidget { width: 134, height: 5, margin: const EdgeInsets.only(bottom: 6), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey50 : AppThemeData.grey800, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey800, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3), + ), + ), ), ), ), @@ -681,11 +1148,22 @@ class DineInDetailsScreen extends StatelessWidget { child: ListView.builder( shrinkWrap: true, physics: const BouncingScrollPhysics(), - itemCount: productModel.vendorModel.value.workingHours!.length, + itemCount: + productModel + .vendorModel + .value + .workingHours! + .length, itemBuilder: (context, dayIndex) { - WorkingHours workingHours = productModel.vendorModel.value.workingHours![dayIndex]; + WorkingHours workingHours = + productModel + .vendorModel + .value + .workingHours![dayIndex]; return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -698,34 +1176,72 @@ class DineInDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), - workingHours.timeslot == null || workingHours.timeslot!.isEmpty + workingHours.timeslot == null || + workingHours.timeslot!.isEmpty ? const SizedBox() : ListView.builder( shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: workingHours.timeslot!.length, + physics: + const NeverScrollableScrollPhysics(), + itemCount: + workingHours.timeslot!.length, itemBuilder: (context, timeIndex) { - Timeslot timeSlotModel = workingHours.timeslot![timeIndex]; + Timeslot timeSlotModel = + workingHours + .timeslot![timeIndex]; return Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all( + 8.0, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey200), + borderRadius: + const BorderRadius.all( + Radius.circular( + 12, + ), + ), + border: Border.all( + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey200, + ), ), child: Center( child: Text( - timeSlotModel.from.toString(), - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + timeSlotModel.from + .toString(), + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: 14, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + ), ), ), ), @@ -733,15 +1249,42 @@ class DineInDetailsScreen extends StatelessWidget { const SizedBox(width: 10), Expanded( child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey200), + borderRadius: + const BorderRadius.all( + Radius.circular( + 12, + ), + ), + border: Border.all( + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey200, + ), ), child: Center( child: Text( - timeSlotModel.to.toString(), - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + timeSlotModel.to + .toString(), + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: 14, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + ), ), ), ), diff --git a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_restaurant_list_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_restaurant_list_screen.dart index e80c5a8..72ce204 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_restaurant_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_restaurant_list_screen.dart @@ -6,7 +6,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/responsive.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../widget/restaurant_image_view.dart'; @@ -119,40 +119,34 @@ class DineInRestaurantListScreen extends StatelessWidget { ) .isNotEmpty) { FavouriteModel - favouriteModel = - FavouriteModel( - restaurantId: - vendorModel.id, - userId: - FireStoreUtils - .getCurrentUid(), - ); + favouriteModel = FavouriteModel( + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); controller.favouriteList .removeWhere( (item) => item.restaurantId == vendorModel.id, ); - await FireStoreUtils - .removeFavouriteRestaurant( - favouriteModel, - ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { FavouriteModel - favouriteModel = - FavouriteModel( - restaurantId: - vendorModel.id, - userId: - FireStoreUtils - .getCurrentUid(), - ); + favouriteModel = FavouriteModel( + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); controller.favouriteList .add(favouriteModel); - await FireStoreUtils - .setFavouriteRestaurant( - favouriteModel, - ); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } }, child: Obx( diff --git a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_screen.dart index 11c9eeb..1fe7b07 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_screeen/dine_in_screen.dart @@ -14,7 +14,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:url_launcher/url_launcher.dart'; import '../../../controllers/theme_controller.dart'; import '../../../models/banner_model.dart'; diff --git a/lib/screen_ui/multi_vendor_service/dine_in_screeen/view_all_category_dine_in_screen.dart b/lib/screen_ui/multi_vendor_service/dine_in_screeen/view_all_category_dine_in_screen.dart index 9d4054f..a33b906 100644 --- a/lib/screen_ui/multi_vendor_service/dine_in_screeen/view_all_category_dine_in_screen.dart +++ b/lib/screen_ui/multi_vendor_service/dine_in_screeen/view_all_category_dine_in_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../home_screen/category_restaurant_screen.dart'; @@ -18,55 +17,79 @@ class ViewAllCategoryDineInScreen extends StatelessWidget { final themeController = Get.find(); final isDark = themeController.isDark.value; return GetX( - init: ViewAllCategoryController(), - builder: (controller) { - return Scaffold( - appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - centerTitle: false, - titleSpacing: 0, - title: Text( - "Categories".tr(), - style: TextStyle( - fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, - ), + init: ViewAllCategoryController(), + builder: (controller) { + return Scaffold( + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + title: Text( + "Categories".tr(), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, ), ), - body: controller.isLoading.value - ? Constant.loader() - : Padding( + ), + body: + controller.isLoading.value + ? Constant.loader() + : Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: GridView.builder( padding: EdgeInsets.zero, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 3.5 / 6, crossAxisSpacing: 6), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + childAspectRatio: 3.5 / 6, + crossAxisSpacing: 6, + ), itemCount: controller.vendorCategoryModel.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { - VendorCategoryModel vendorCategoryModel = controller.vendorCategoryModel[index]; + VendorCategoryModel vendorCategoryModel = + controller.vendorCategoryModel[index]; return InkWell( onTap: () { - Get.to(const CategoryRestaurantScreen(), arguments: {"vendorCategoryModel": vendorCategoryModel, "dineIn": true}); + Get.to( + const CategoryRestaurantScreen(), + arguments: { + "vendorCategoryModel": vendorCategoryModel, + "dineIn": true, + }, + ); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 4, + vertical: 6, + ), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( side: BorderSide( width: 1, strokeAlign: BorderSide.strokeAlignOutside, - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + color: + isDark + ? AppThemeData.grey800 + : AppThemeData.grey100, ), borderRadius: BorderRadius.circular(100), ), ), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( @@ -74,23 +97,31 @@ class ViewAllCategoryDineInScreen extends StatelessWidget { height: 60, child: ClipOval( child: NetworkImageWidget( - imageUrl: vendorCategoryModel.photo.toString(), + imageUrl: + vendorCategoryModel.photo + .toString(), fit: BoxFit.cover, ), ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: Text( '${vendorCategoryModel.title}', textAlign: TextAlign.center, maxLines: 2, style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, fontFamily: AppThemeData.medium, ), ), - ) + ), ], ), ), @@ -99,7 +130,8 @@ class ViewAllCategoryDineInScreen extends StatelessWidget { }, ), ), - ); - }); + ); + }, + ); } } diff --git a/lib/screen_ui/multi_vendor_service/edit_profile_screen/edit_profile_screen.dart b/lib/screen_ui/multi_vendor_service/edit_profile_screen/edit_profile_screen.dart index 33fa7e6..2811025 100644 --- a/lib/screen_ui/multi_vendor_service/edit_profile_screen/edit_profile_screen.dart +++ b/lib/screen_ui/multi_vendor_service/edit_profile_screen/edit_profile_screen.dart @@ -10,7 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:image_picker/image_picker.dart'; import '../../../controllers/theme_controller.dart'; @@ -25,7 +25,12 @@ class EditProfileScreen extends StatelessWidget { init: EditProfileController(), builder: (controller) { return Scaffold( - appBar: AppBar(centerTitle: false, titleSpacing: 0, backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface), + appBar: AppBar( + centerTitle: false, + titleSpacing: 0, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -34,11 +39,24 @@ class EditProfileScreen extends StatelessWidget { children: [ Text( "Profile Information".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( - "View and update your personal details, contact information, and preferences.".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + "View and update your personal details, contact information, and preferences." + .tr(), + style: TextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 20), Center( @@ -47,12 +65,25 @@ class EditProfileScreen extends StatelessWidget { controller.profileImage.isEmpty ? ClipRRect( borderRadius: BorderRadius.circular(60), - child: Image.asset(Constant.userPlaceHolder, height: Responsive.width(24, context), width: Responsive.width(24, context), fit: BoxFit.cover), + child: Image.asset( + Constant.userPlaceHolder, + height: Responsive.width(24, context), + width: Responsive.width(24, context), + fit: BoxFit.cover, + ), ) - : Constant().hasValidUrl(controller.profileImage.value) == false + : Constant().hasValidUrl( + controller.profileImage.value, + ) == + false ? ClipRRect( borderRadius: BorderRadius.circular(60), - child: Image.file(File(controller.profileImage.value), height: Responsive.width(24, context), width: Responsive.width(24, context), fit: BoxFit.cover), + child: Image.file( + File(controller.profileImage.value), + height: Responsive.width(24, context), + width: Responsive.width(24, context), + fit: BoxFit.cover, + ), ) : ClipRRect( borderRadius: BorderRadius.circular(60), @@ -61,7 +92,12 @@ class EditProfileScreen extends StatelessWidget { imageUrl: controller.profileImage.value, height: Responsive.width(24, context), width: Responsive.width(24, context), - errorWidget: Image.asset(Constant.userPlaceHolder, fit: BoxFit.cover, height: Responsive.width(24, context), width: Responsive.width(24, context)), + errorWidget: Image.asset( + Constant.userPlaceHolder, + fit: BoxFit.cover, + height: Responsive.width(24, context), + width: Responsive.width(24, context), + ), ), ), Positioned( @@ -80,13 +116,37 @@ class EditProfileScreen extends StatelessWidget { const SizedBox(height: 20), Row( children: [ - Expanded(child: TextFieldWidget(title: 'First Name'.tr(), controller: controller.firstNameController.value, hintText: 'First Name'.tr())), + Expanded( + child: TextFieldWidget( + title: 'First Name'.tr(), + controller: controller.firstNameController.value, + hintText: 'First Name'.tr(), + ), + ), const SizedBox(width: 10), - Expanded(child: TextFieldWidget(title: 'Last Name'.tr(), controller: controller.lastNameController.value, hintText: 'Last Name'.tr())), + Expanded( + child: TextFieldWidget( + title: 'Last Name'.tr(), + controller: controller.lastNameController.value, + hintText: 'Last Name'.tr(), + ), + ), ], ), - TextFieldWidget(title: 'Email'.tr(), textInputType: TextInputType.emailAddress, controller: controller.emailController.value, hintText: 'Email'.tr(), enable: false), - TextFieldWidget(title: 'Phone Number'.tr(), textInputType: TextInputType.emailAddress, controller: controller.phoneNumberController.value, hintText: 'Phone Number'.tr(), enable: false), + TextFieldWidget( + title: 'Email'.tr(), + textInputType: TextInputType.emailAddress, + controller: controller.emailController.value, + hintText: 'Email'.tr(), + enable: false, + ), + TextFieldWidget( + title: 'Phone Number'.tr(), + textInputType: TextInputType.emailAddress, + controller: controller.phoneNumberController.value, + hintText: 'Phone Number'.tr(), + enable: false, + ), ], ), ), @@ -97,7 +157,7 @@ class EditProfileScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(bottom: 20), child: RoundedButtonFill( - borderRadius: 10.r, + borderRadius: 10.r, title: "Save Details".tr(), height: 5.5, color: AppThemeData.primary300, @@ -114,7 +174,10 @@ class EditProfileScreen extends StatelessWidget { ); } - Future buildBottomSheet(BuildContext context, EditProfileController controller) { + Future buildBottomSheet( + BuildContext context, + EditProfileController controller, + ) { return showModalBottomSheet( context: context, builder: (context) { @@ -125,7 +188,16 @@ class EditProfileScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Padding(padding: const EdgeInsets.only(top: 15), child: Text("please select".tr(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600))), + Padding( + padding: const EdgeInsets.only(top: 15), + child: Text( + "please select".tr(), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -135,8 +207,20 @@ class EditProfileScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - IconButton(onPressed: () => controller.pickFile(source: ImageSource.camera), icon: const Icon(Icons.camera_alt, size: 32)), - Padding(padding: const EdgeInsets.only(top: 3), child: Text("camera".tr(), style: const TextStyle())), + IconButton( + onPressed: + () => controller.pickFile( + source: ImageSource.camera, + ), + icon: const Icon(Icons.camera_alt, size: 32), + ), + Padding( + padding: const EdgeInsets.only(top: 3), + child: Text( + "camera".tr(), + style: const TextStyle(), + ), + ), ], ), ), @@ -146,8 +230,23 @@ class EditProfileScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - IconButton(onPressed: () => controller.pickFile(source: ImageSource.gallery), icon: const Icon(Icons.photo_library_sharp, size: 32)), - Padding(padding: const EdgeInsets.only(top: 3), child: Text("gallery".tr(), style: const TextStyle())), + IconButton( + onPressed: + () => controller.pickFile( + source: ImageSource.gallery, + ), + icon: const Icon( + Icons.photo_library_sharp, + size: 32, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 3), + child: Text( + "gallery".tr(), + style: const TextStyle(), + ), + ), ], ), ), diff --git a/lib/screen_ui/multi_vendor_service/favourite_screens/favourite_screen.dart b/lib/screen_ui/multi_vendor_service/favourite_screens/favourite_screen.dart index baa570c..4eb1bf0 100644 --- a/lib/screen_ui/multi_vendor_service/favourite_screens/favourite_screen.dart +++ b/lib/screen_ui/multi_vendor_service/favourite_screens/favourite_screen.dart @@ -12,7 +12,7 @@ import '../../../controllers/theme_controller.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; import '../../../widget/restaurant_image_view.dart'; @@ -30,12 +30,15 @@ class FavouriteScreen extends StatelessWidget { init: FavouriteController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: controller.isLoading.value ? Constant.loader() : Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: Column( children: [ Padding( @@ -45,7 +48,15 @@ class FavouriteScreen extends StatelessWidget { Expanded( child: Text( "Your Favourites, All in One Place".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), ), //SvgPicture.asset("assets/images/ic_favourite.svg"), @@ -57,22 +68,44 @@ class FavouriteScreen extends StatelessWidget { child: Constant.userModel == null ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Image.asset("assets/images/login.gif", height: 120), + Image.asset( + "assets/images/login.gif", + height: 120, + ), const SizedBox(height: 12), Text( "Please Log In to Continue".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -91,11 +124,19 @@ class FavouriteScreen extends StatelessWidget { : Column( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(120), + ), ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -104,19 +145,50 @@ class FavouriteScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - controller.favouriteRestaurant.value = true; + controller + .favouriteRestaurant + .value = true; }, child: Container( decoration: - controller.favouriteRestaurant.value == false + controller + .favouriteRestaurant + .value == + false ? null - : ShapeDecoration(color: AppThemeData.grey900, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + : ShapeDecoration( + color: + AppThemeData + .grey900, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Text( - "Favourite Store".tr(), - textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + "Favourite Store" + .tr(), + textAlign: + TextAlign.center, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ), @@ -125,28 +197,57 @@ class FavouriteScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - controller.favouriteRestaurant.value = false; + controller + .favouriteRestaurant + .value = false; }, child: Container( decoration: - controller.favouriteRestaurant.value == true + controller + .favouriteRestaurant + .value == + true ? null - : ShapeDecoration(color: AppThemeData.grey900, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + : ShapeDecoration( + color: + AppThemeData + .grey900, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Text( "Favourite Item".tr(), - textAlign: TextAlign.center, + textAlign: + TextAlign.center, style: TextStyle( - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData + .semiBold, color: - controller.favouriteRestaurant.value == true + controller + .favouriteRestaurant + .value == + true ? isDark - ? AppThemeData.grey400 - : AppThemeData.grey500 + ? AppThemeData + .grey400 + : AppThemeData + .grey500 : isDark - ? AppThemeData.primary300 - : AppThemeData.primary300, + ? AppThemeData + .primary300 + : AppThemeData + .primary300, ), ), ), @@ -161,79 +262,190 @@ class FavouriteScreen extends StatelessWidget { const SizedBox(height: 20), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 18), + padding: const EdgeInsets.symmetric( + horizontal: 18, + ), child: - controller.favouriteRestaurant.value - ? controller.favouriteVendorList.isEmpty - ? Constant.showEmptyView(message: "Favourite Store not found.".tr()) + controller + .favouriteRestaurant + .value + ? controller + .favouriteVendorList + .isEmpty + ? Constant.showEmptyView( + message: + "Favourite Store not found." + .tr(), + ) : ListView.builder( shrinkWrap: true, - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - itemCount: controller.favouriteVendorList.length, - itemBuilder: (BuildContext context, int index) { - VendorModel vendorModel = controller.favouriteVendorList[index]; + padding: + EdgeInsets.zero, + scrollDirection: + Axis.vertical, + itemCount: + controller + .favouriteVendorList + .length, + itemBuilder: ( + BuildContext context, + int index, + ) { + VendorModel + vendorModel = + controller + .favouriteVendorList[index]; return InkWell( onTap: () { ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: { + "vendorModel": + vendorModel, + }, + ); // Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); }, child: Padding( - padding: const EdgeInsets.only(bottom: 20), + padding: + const EdgeInsets.only( + bottom: 20, + ), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + color: + isDark + ? AppThemeData + .grey900 + : AppThemeData + .grey50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Stack( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular( + 16, + ), + topRight: Radius.circular( + 16, + ), + ), child: Stack( children: [ - RestaurantImageView(vendorModel: vendorModel), + RestaurantImageView( + vendorModel: + vendorModel, + ), Container( - height: Responsive.height(20, context), - width: Responsive.width(100, context), + height: Responsive.height( + 20, + context, + ), + width: Responsive.width( + 100, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), - end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + begin: const Alignment( + -0.00, + -1.00, + ), + end: const Alignment( + 0, + 1, + ), + colors: [ + Colors.black.withOpacity( + 0, + ), + const Color( + 0xFF111827, + ), + ], ), ), ), Positioned( - right: 10, - top: 10, + right: + 10, + top: + 10, child: InkWell( onTap: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == vendorModel.id).isNotEmpty) { + if (controller.favouriteList + .where( + ( + p0, + ) => + p0.restaurantId == + vendorModel.id, + ) + .isNotEmpty) { FavouriteModel favouriteModel = FavouriteModel( - restaurantId: vendorModel.id, - userId: FireStoreUtils.getCurrentUid(), + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.removeWhere( + ( + item, + ) => + item.restaurantId == + vendorModel.id, + ); + controller.favouriteVendorList.removeAt( + index, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, ); - controller.favouriteList.removeWhere((item) => item.restaurantId == vendorModel.id); - controller.favouriteVendorList.removeAt(index); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); } else { FavouriteModel favouriteModel = FavouriteModel( - restaurantId: vendorModel.id, - userId: FireStoreUtils.getCurrentUid(), + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.add( + favouriteModel, + ); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, ); - controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); } }, child: Obx( () => - controller.favouriteList.where((p0) => p0.restaurantId == vendorModel.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteList + .where( + ( + p0, + ) => + p0.restaurantId == + vendorModel.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), ), @@ -241,86 +453,171 @@ class FavouriteScreen extends StatelessWidget { ), ), Transform.translate( - offset: Offset(Responsive.width(-3, context), Responsive.height(17.5, context)), + offset: Offset( + Responsive.width( + -3, + context, + ), + Responsive.height( + 17.5, + context, + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, children: [ Visibility( - visible: (vendorModel.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (vendorModel.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true), child: Row( children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: const EdgeInsets.symmetric( + horizontal: + 10, + vertical: + 7, + ), decoration: BoxDecoration( - color: AppThemeData.success300, - borderRadius: BorderRadius.circular(120), // Optional + color: + AppThemeData.success300, + borderRadius: BorderRadius.circular( + 120, + ), // Optional ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg"), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + ), + const SizedBox( + width: + 5, + ), Text( "Free Delivery".tr(), style: TextStyle( - fontSize: 14, - color: AppThemeData.success600, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 14, + color: + AppThemeData.success600, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], ), ), - const SizedBox(width: 6), + const SizedBox( + width: + 6, + ), ], ), ), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: const EdgeInsets.symmetric( + horizontal: + 10, + vertical: + 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ SvgPicture.asset( "assets/icons/ic_star.svg", - colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn), + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: + 5, ), - const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", style: TextStyle( - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], ), ), - const SizedBox(width: 6), + const SizedBox( + width: + 6, + ), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: const EdgeInsets.symmetric( + horizontal: + 10, + vertical: + 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.ecommerce600 : AppThemeData.ecommerce50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData.ecommerce600 + : AppThemeData.ecommerce50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ SvgPicture.asset( "assets/icons/ic_map_distance.svg", - colorFilter: ColorFilter.mode(AppThemeData.ecommerce300, BlendMode.srcIn), + colorFilter: ColorFilter.mode( + AppThemeData.ecommerce300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: + 5, ), - const SizedBox(width: 5), Text( "${Constant.getDistance(lat1: vendorModel.latitude.toString(), lng1: vendorModel.longitude.toString(), lat2: Constant.selectedLocation.location!.latitude.toString(), lng2: Constant.selectedLocation.location!.longitude.toString())} ${Constant.distanceType}", style: TextStyle( - fontSize: 14, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 14, + color: + isDark + ? AppThemeData.ecommerce300 + : AppThemeData.ecommerce300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -331,38 +628,64 @@ class FavouriteScreen extends StatelessWidget { ), ], ), - const SizedBox(height: 15), + const SizedBox( + height: + 15, + ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: + 16, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( vendorModel.title.toString(), - textAlign: TextAlign.start, - maxLines: 1, + textAlign: + TextAlign.start, + maxLines: + 1, style: TextStyle( - fontSize: 18, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontSize: + 18, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), Text( vendorModel.location.toString(), - textAlign: TextAlign.start, - maxLines: 1, + textAlign: + TextAlign.start, + maxLines: + 1, style: TextStyle( - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.medium, + fontWeight: + FontWeight.w500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), ], ), ), - const SizedBox(height: 10), + const SizedBox( + height: + 10, + ), ], ), ), @@ -370,114 +693,249 @@ class FavouriteScreen extends StatelessWidget { ); }, ) - : controller.favouriteFoodList.isEmpty - ? Constant.showEmptyView(message: "Favourite Item not found.".tr()) + : controller + .favouriteFoodList + .isEmpty + ? Constant.showEmptyView( + message: + "Favourite Item not found." + .tr(), + ) : ListView.builder( - itemCount: controller.favouriteFoodList.length, + itemCount: + controller + .favouriteFoodList + .length, shrinkWrap: true, padding: EdgeInsets.zero, - itemBuilder: (context, index) { - ProductModel productModel = controller.favouriteFoodList[index]; + itemBuilder: ( + context, + index, + ) { + ProductModel + productModel = + controller + .favouriteFoodList[index]; return FutureBuilder( - future: getPrice(productModel), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + future: getPrice( + productModel, + ), + builder: ( + context, + snapshot, + ) { + if (snapshot + .connectionState == + ConnectionState + .waiting) { return Constant.loader(); } else { - if (snapshot.hasError) { - return Center(child: Text('${"error".tr()}: ${snapshot.error}')); - } else if (snapshot.data == null) { + if (snapshot + .hasError) { + return Center( + child: Text( + '${"error".tr()}: ${snapshot.error}', + ), + ); + } else if (snapshot + .data == + null) { return const SizedBox(); } else { - Map map = snapshot.data!; - String price = map['price']; - String disPrice = map['disPrice']; + Map< + String, + dynamic + > + map = + snapshot + .data!; + String price = + map['price']; + String disPrice = + map['disPrice']; return InkWell( onTap: () async { - await FireStoreUtils.getVendorById(productModel.vendorID.toString()).then((value) { - if (value != null) { + await FireStoreUtils.getVendorById( + productModel + .vendorID + .toString(), + ).then(( + value, + ) { + if (value != + null) { ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": value}); + Get.to( + const RestaurantDetailsScreen(), + arguments: { + "vendorModel": + value, + }, + ); // Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": value}); } }); }, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: + const EdgeInsets.symmetric( + vertical: + 5, + ), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: + 14, + vertical: + 14, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ - productModel.nonveg == true - ? SvgPicture.asset("assets/icons/ic_nonveg.svg") - : SvgPicture.asset("assets/icons/ic_veg.svg"), - const SizedBox(width: 5), + productModel.nonveg == + true + ? SvgPicture.asset( + "assets/icons/ic_nonveg.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_veg.svg", + ), + const SizedBox( + width: + 5, + ), Text( - productModel.nonveg == true ? "Non Veg.".tr() : "Pure veg.".tr(), + productModel.nonveg == + true + ? "Non Veg.".tr() + : "Pure veg.".tr(), style: TextStyle( - color: productModel.nonveg == true ? AppThemeData.danger300 : AppThemeData.success400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + productModel.nonveg == + true + ? AppThemeData.danger300 + : AppThemeData.success400, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], ), - const SizedBox(height: 5), + const SizedBox( + height: + 5, + ), Text( productModel.name.toString(), style: TextStyle( - fontSize: 18, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), - double.parse(disPrice) <= 0 + double.parse( + disPrice, + ) <= + 0 ? Text( - Constant.amountShow(amount: price), + Constant.amountShow( + amount: + price, + ), style: TextStyle( - fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ) : Row( children: [ Text( - Constant.amountShow(amount: disPrice), + Constant.amountShow( + amount: + disPrice, + ), style: TextStyle( - fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), - const SizedBox(width: 5), + const SizedBox( + width: + 5, + ), Text( - Constant.amountShow(amount: price), + Constant.amountShow( + amount: + price, + ), style: TextStyle( - fontSize: 14, - decoration: TextDecoration.lineThrough, - decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - color: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontSize: + 14, + decoration: + TextDecoration.lineThrough, + decorationColor: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -486,83 +944,177 @@ class FavouriteScreen extends StatelessWidget { children: [ SvgPicture.asset( "assets/icons/ic_star.svg", - colorFilter: const ColorFilter.mode(AppThemeData.warning300, BlendMode.srcIn), + colorFilter: const ColorFilter.mode( + AppThemeData.warning300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: + 5, ), - const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount!.toStringAsFixed(0), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsCount!.toStringAsFixed(0)})", style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.regular, + fontWeight: + FontWeight.w500, ), ), ], ), Text( "${productModel.description}", - maxLines: 2, + maxLines: + 2, style: TextStyle( - overflow: TextOverflow.ellipsis, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w400, + overflow: + TextOverflow.ellipsis, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.regular, + fontWeight: + FontWeight.w400, ), ), ], ), ), - const SizedBox(width: 6), + const SizedBox( + width: + 6, + ), ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: const BorderRadius.all( + Radius.circular( + 16, + ), + ), child: Stack( children: [ NetworkImageWidget( - imageUrl: productModel.photo.toString(), - fit: BoxFit.cover, - height: Responsive.height(16, context), - width: Responsive.width(34, context), + imageUrl: + productModel.photo.toString(), + fit: + BoxFit.cover, + height: Responsive.height( + 16, + context, + ), + width: Responsive.width( + 34, + context, + ), ), Container( - height: Responsive.height(16, context), - width: Responsive.width(34, context), + height: Responsive.height( + 16, + context, + ), + width: Responsive.width( + 34, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), - end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + begin: const Alignment( + -0.00, + -1.00, + ), + end: const Alignment( + 0, + 1, + ), + colors: [ + Colors.black.withOpacity( + 0, + ), + const Color( + 0xFF111827, + ), + ], ), ), ), Positioned( - right: 10, - top: 10, + right: + 10, + top: + 10, child: InkWell( onTap: () async { - if (controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty) { + if (controller.favouriteItemList + .where( + ( + p0, + ) => + p0.productId == + productModel.id, + ) + .isNotEmpty) { FavouriteItemModel favouriteModel = FavouriteItemModel( - productId: productModel.id, - storeId: productModel.vendorID, - userId: FireStoreUtils.getCurrentUid(), + productId: + productModel.id, + storeId: + productModel.vendorID, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList.removeWhere( + ( + item, + ) => + item.productId == + productModel.id, + ); + controller.favouriteFoodList.removeAt( + index, + ); + await FireStoreUtils.removeFavouriteItem( + favouriteModel, ); - controller.favouriteItemList.removeWhere((item) => item.productId == productModel.id); - controller.favouriteFoodList.removeAt(index); - await FireStoreUtils.removeFavouriteItem(favouriteModel); } else { FavouriteItemModel favouriteModel = FavouriteItemModel( - productId: productModel.id, - storeId: productModel.vendorID, - userId: FireStoreUtils.getCurrentUid(), + productId: + productModel.id, + storeId: + productModel.vendorID, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList.add( + favouriteModel, + ); + await FireStoreUtils.setFavouriteItem( + favouriteModel, ); - controller.favouriteItemList.add(favouriteModel); - await FireStoreUtils.setFavouriteItem(favouriteModel); } }, child: Obx( () => - controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteItemList + .where( + ( + p0, + ) => + p0.productId == + productModel.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), ), @@ -605,24 +1157,56 @@ class FavouriteScreen extends StatelessWidget { print(productModel.price); print(productModel.disPrice); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(productModel.vendorID.toString()); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + productModel.vendorID.toString(), + ); if (productModel.itemAttribute != null) { if (productModel.itemAttribute!.attributes!.isNotEmpty) { for (var element in productModel.itemAttribute!.attributes!) { if (element.attributeOptions!.isNotEmpty) { - selectedVariants.add(productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString()); - selectedIndexVariants.add('${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}'); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedVariants.add( + productModel + .itemAttribute! + .attributes![productModel.itemAttribute!.attributes!.indexOf( + element, + )] + .attributeOptions![0] + .toString(), + ); + selectedIndexVariants.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', + ); + selectedIndexArray.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { - price = Constant.productCommissionPrice(vendorModel!, productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0'); + if (productModel.itemAttribute!.variants! + .where((element) => element.variantSku == selectedVariants.join('-')) + .isNotEmpty) { + price = Constant.productCommissionPrice( + vendorModel!, + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', + ); disPrice = Constant.productCommissionPrice(vendorModel, '0'); } } else { - price = Constant.productCommissionPrice(vendorModel!, productModel.price.toString()); - disPrice = Constant.productCommissionPrice(vendorModel, productModel.disPrice.toString()); + price = Constant.productCommissionPrice( + vendorModel!, + productModel.price.toString(), + ); + disPrice = Constant.productCommissionPrice( + vendorModel, + productModel.disPrice.toString(), + ); } return {'price': price, 'disPrice': disPrice}; diff --git a/lib/screen_ui/multi_vendor_service/forgot_password_screen/forgot_password_screen.dart b/lib/screen_ui/multi_vendor_service/forgot_password_screen/forgot_password_screen.dart index e70da70..cc6bef3 100644 --- a/lib/screen_ui/multi_vendor_service/forgot_password_screen/forgot_password_screen.dart +++ b/lib/screen_ui/multi_vendor_service/forgot_password_screen/forgot_password_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/text_field_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -21,14 +20,31 @@ class ForgotPasswordScreen extends StatelessWidget { init: ForgotPasswordController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Forgot Password".tr(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold)), - Text("No worries!! We’ll send you reset instructions".tr(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.regular)), + Text( + "Forgot Password".tr(), + style: TextStyle( + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), + Text( + "No worries!! We’ll send you reset instructions".tr(), + style: TextStyle( + color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.regular, + ), + ), const SizedBox(height: 32), TextFieldWidget( title: 'Email Address'.tr(), @@ -36,7 +52,13 @@ class ForgotPasswordScreen extends StatelessWidget { hintText: 'Enter email address'.tr(), prefix: Padding( padding: const EdgeInsets.all(12), - child: SvgPicture.asset("assets/icons/ic_mail.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey300 : AppThemeData.grey600, BlendMode.srcIn)), + child: SvgPicture.asset( + "assets/icons/ic_mail.svg", + colorFilter: ColorFilter.mode( + isDark ? AppThemeData.grey300 : AppThemeData.grey600, + BlendMode.srcIn, + ), + ), ), ), const SizedBox(height: 32), @@ -45,8 +67,12 @@ class ForgotPasswordScreen extends StatelessWidget { color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () async { - if (controller.emailEditingController.value.text.trim().isEmpty) { - ShowToastDialog.showToast("Please enter valid email".tr()); + if (controller.emailEditingController.value.text + .trim() + .isEmpty) { + ShowToastDialog.showToast( + "Please enter valid email".tr(), + ); } else { controller.forgotPassword(); } diff --git a/lib/screen_ui/multi_vendor_service/gift_card/gift_card_screen.dart b/lib/screen_ui/multi_vendor_service/gift_card/gift_card_screen.dart index d4f2197..921276d 100644 --- a/lib/screen_ui/multi_vendor_service/gift_card/gift_card_screen.dart +++ b/lib/screen_ui/multi_vendor_service/gift_card/gift_card_screen.dart @@ -12,7 +12,7 @@ import 'package:easy_localization/easy_localization.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:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; import 'history_gift_card.dart'; @@ -29,13 +29,18 @@ class GiftCardScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( "Customize Gift Card".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), actions: [ InkWell( @@ -69,26 +74,54 @@ class GiftCardScreen extends StatelessWidget { itemCount: controller.giftCardList.length, onPageChanged: (value) { controller.selectedPageIndex.value = value; - controller.selectedGiftCard.value = controller.giftCardList[controller.selectedPageIndex.value]; + controller.selectedGiftCard.value = + controller.giftCardList[controller + .selectedPageIndex + .value]; - controller.messageController.value.text = controller.giftCardList[controller.selectedPageIndex.value].message.toString(); + controller.messageController.value.text = + controller + .giftCardList[controller + .selectedPageIndex + .value] + .message + .toString(); }, scrollDirection: Axis.horizontal, controller: controller.pageController, itemBuilder: (context, index) { - GiftCardsModel giftCardModel = controller.giftCardList[index]; + GiftCardsModel giftCardModel = + controller.giftCardList[index]; return InkWell( onTap: () { - controller.selectedGiftCard.value = giftCardModel; - controller.messageController.value.text = controller.selectedGiftCard.value.message.toString(); + controller.selectedGiftCard.value = + giftCardModel; + controller.messageController.value.text = + controller + .selectedGiftCard + .value + .message + .toString(); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), border: Border.all(color: AppThemeData.primary300)), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: AppThemeData.primary300, + ), + ), child: ClipRRect( borderRadius: BorderRadius.circular(10), - child: NetworkImageWidget(imageUrl: giftCardModel.image.toString(), width: Responsive.width(80, context), fit: BoxFit.cover), + child: NetworkImageWidget( + imageUrl: + giftCardModel.image.toString(), + width: Responsive.width(80, context), + fit: BoxFit.cover, + ), ), ), ), @@ -101,14 +134,32 @@ class GiftCardScreen extends StatelessWidget { title: 'Choose an amount'.tr(), controller: controller.amountController.value, hintText: 'Enter gift card amount'.tr(), - textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true), + textInputType: + const TextInputType.numberWithOptions( + signed: true, + decimal: true, + ), textInputAction: TextInputAction.done, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9]'))], + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp('[0-9]'), + ), + ], prefix: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 14, + ), child: Text( Constant.currencyModel!.symbol.tr(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontSize: 18), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontSize: 18, + ), ), ), onchange: (value) { @@ -126,17 +177,25 @@ class GiftCardScreen extends StatelessWidget { return Obx( () => InkWell( onTap: () { - controller.selectedAmount.value = controller.amountList[index]; - controller.amountController.value.text = controller.amountList[index]; + controller.selectedAmount.value = + controller.amountList[index]; + controller.amountController.value.text = + controller.amountList[index]; }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), + padding: const EdgeInsets.symmetric( + horizontal: 5, + ), child: Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(40)), + borderRadius: const BorderRadius.all( + Radius.circular(40), + ), border: Border.all( color: - controller.selectedAmount == controller.amountList[index] + controller.selectedAmount == + controller + .amountList[index] ? AppThemeData.primary300 : isDark ? AppThemeData.grey400 @@ -144,11 +203,24 @@ class GiftCardScreen extends StatelessWidget { ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Center( child: Text( - Constant.amountShow(amount: controller.amountList[index]), - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + Constant.amountShow( + amount: + controller + .amountList[index], + ), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ), ), @@ -160,7 +232,12 @@ class GiftCardScreen extends StatelessWidget { ), ), const SizedBox(height: 40), - TextFieldWidget(title: 'Add Message (Optional)'.tr(), controller: controller.messageController.value, hintText: 'Add message here....'.tr(), maxLine: 6), + TextFieldWidget( + title: 'Add Message (Optional)'.tr(), + controller: controller.messageController.value, + hintText: 'Add message here....'.tr(), + maxLine: 6, + ), ], ), ), @@ -179,7 +256,10 @@ class GiftCardScreen extends StatelessWidget { onPress: () async { if (controller.amountController.value.text.isNotEmpty) { if (Constant.userModel == null) { - ShowToastDialog.showToast("Please log in to the application. You are not logged in.".tr()); + ShowToastDialog.showToast( + "Please log in to the application. You are not logged in." + .tr(), + ); } else { giftCardBottomSheet(context, controller); } @@ -195,12 +275,17 @@ class GiftCardScreen extends StatelessWidget { ); } - Future giftCardBottomSheet(BuildContext context, GiftCardController controller) { + Future giftCardBottomSheet( + BuildContext context, + GiftCardController controller, + ) { return showModalBottomSheet( context: context, isScrollControlled: true, isDismissible: true, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), clipBehavior: Clip.antiAliasWithSaveLayer, builder: (context) => FractionallySizedBox( @@ -213,7 +298,10 @@ class GiftCardScreen extends StatelessWidget { () => Scaffold( body: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -221,17 +309,34 @@ class GiftCardScreen extends StatelessWidget { const SizedBox(height: 20), ClipRRect( borderRadius: BorderRadius.circular(10), - child: NetworkImageWidget(imageUrl: controller.selectedGiftCard.value.image.toString(), height: Responsive.height(20, context), width: Responsive.width(100, context)), + child: NetworkImageWidget( + imageUrl: + controller.selectedGiftCard.value.image + .toString(), + height: Responsive.height(20, context), + width: Responsive.width(100, context), + ), ), const SizedBox(height: 10), Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Container( padding: const EdgeInsets.all(8), - decoration: ShapeDecoration(color: AppThemeData.ecommerce50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: AppThemeData.ecommerce50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Text( - 'Complete payment and share this e-gift card with loved ones using any app'.tr(), - style: TextStyle(color: AppThemeData.ecommerce300, fontSize: 14, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + 'Complete payment and share this e-gift card with loved ones using any app' + .tr(), + style: TextStyle( + color: AppThemeData.ecommerce300, + fontSize: 14, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ), ), @@ -241,48 +346,114 @@ class GiftCardScreen extends StatelessWidget { Text( "Bill Details".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Sub Total".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.amountController.value.text), + Constant.amountShow( + amount: + controller + .amountController + .value + .text, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Grand Total".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.amountController.value.text), + Constant.amountShow( + amount: + controller + .amountController + .value + .text, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -295,9 +466,17 @@ class GiftCardScreen extends StatelessWidget { const SizedBox(height: 20), Center( child: Text( - "${'Gift Card expire'.tr()} ${controller.selectedGiftCard.value.expiryDay} ${'days after purchase'.tr()}".tr(), + "${'Gift Card expire'.tr()} ${controller.selectedGiftCard.value.expiryDay} ${'days after purchase'.tr()}" + .tr(), textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + ), ), ), ], @@ -305,12 +484,17 @@ class GiftCardScreen extends StatelessWidget { ), ), bottomNavigationBar: Container( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: Padding( padding: const EdgeInsets.only(bottom: 20), child: RoundedButtonFill( - title: "${'Pay'.tr()} ${Constant.amountShow(amount: controller.amountController.value.text)}", + title: + "${'Pay'.tr()} ${Constant.amountShow(amount: controller.amountController.value.text)}", height: 5.5, color: AppThemeData.primary300, textColor: AppThemeData.grey50, diff --git a/lib/screen_ui/multi_vendor_service/gift_card/history_gift_card.dart b/lib/screen_ui/multi_vendor_service/gift_card/history_gift_card.dart index 1322201..6d92fb3 100644 --- a/lib/screen_ui/multi_vendor_service/gift_card/history_gift_card.dart +++ b/lib/screen_ui/multi_vendor_service/gift_card/history_gift_card.dart @@ -4,7 +4,7 @@ import 'package:customer/models/gift_cards_order_model.dart'; import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../widget/my_separator.dart'; @@ -19,7 +19,12 @@ class HistoryGiftCard extends StatelessWidget { init: HistoryGiftCardController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: controller.isLoading.value ? Constant.loader() @@ -27,61 +32,114 @@ class HistoryGiftCard extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: controller.giftCardsOrderList.isEmpty - ? Constant.showEmptyView(message: "Purchased Gift card not found".tr()) + ? Constant.showEmptyView( + message: "Purchased Gift card not found".tr(), + ) : ListView.builder( itemCount: controller.giftCardsOrderList.length, shrinkWrap: true, itemBuilder: (context, index) { - GiftCardsOrderModel giftCardOrderModel = controller.giftCardsOrderList[index]; + GiftCardsOrderModel giftCardOrderModel = + controller.giftCardsOrderList[index]; return Container( - margin: const EdgeInsets.symmetric(vertical: 4), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + margin: const EdgeInsets.symmetric( + vertical: 4, + ), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(10), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( - giftCardOrderModel.giftTitle.toString(), + giftCardOrderModel.giftTitle + .toString(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ), ), Text( - Constant.amountShow(amount: giftCardOrderModel.price.toString()), + Constant.amountShow( + amount: + giftCardOrderModel.price + .toString(), + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), Row( children: [ Expanded( child: Text( "Gift Code".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData + .grey600, + fontFamily: + AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), ), Text( - giftCardOrderModel.giftCode.toString().replaceAllMapped(RegExp(r".{4}"), (match) => "${match.group(0)} "), + giftCardOrderModel.giftCode + .toString() + .replaceAllMapped( + RegExp(r".{4}"), + (match) => + "${match.group(0)} ", + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ), @@ -93,16 +151,33 @@ class HistoryGiftCard extends StatelessWidget { Expanded( child: Text( "Gift Pin".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData + .grey600, + fontFamily: + AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), ), - giftCardOrderModel.isPasswordShow == true + giftCardOrderModel.isPasswordShow == + true ? Text( - giftCardOrderModel.giftPin.toString(), + giftCardOrderModel.giftPin + .toString(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ) @@ -110,60 +185,107 @@ class HistoryGiftCard extends StatelessWidget { "****", style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ), const SizedBox(width: 10), - giftCardOrderModel.isPasswordShow == true + giftCardOrderModel.isPasswordShow == + true ? InkWell( onTap: () { - controller.updateList(index); + controller.updateList( + index, + ); controller.update(); }, - child: const Icon(Icons.visibility_off), + child: const Icon( + Icons.visibility_off, + ), ) : InkWell( onTap: () { - controller.updateList(index); + controller.updateList( + index, + ); controller.update(); }, - child: const Icon(Icons.remove_red_eye), + child: const Icon( + Icons.remove_red_eye, + ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), Row( children: [ InkWell( onTap: () { controller.share( - giftCardOrderModel.giftCode.toString(), - giftCardOrderModel.giftPin.toString(), - giftCardOrderModel.message.toString(), - giftCardOrderModel.price.toString(), - giftCardOrderModel.expireDate!, + giftCardOrderModel.giftCode + .toString(), + giftCardOrderModel.giftPin + .toString(), + giftCardOrderModel.message + .toString(), + giftCardOrderModel.price + .toString(), + giftCardOrderModel + .expireDate!, ); }, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 6, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + color: + isDark + ? AppThemeData.grey700 + : AppThemeData + .grey200, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), ), child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: + MainAxisSize.min, children: [ Text( 'Share'.tr(), style: TextStyle( - color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, fontSize: 14, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, height: 0.11, ), ), @@ -175,11 +297,20 @@ class HistoryGiftCard extends StatelessWidget { ), const Expanded(child: SizedBox()), Text( - giftCardOrderModel.redeem == true ? "Redeemed".tr() : "Not Redeem".tr(), + giftCardOrderModel.redeem == true + ? "Redeemed".tr() + : "Not Redeem".tr(), style: TextStyle( fontSize: 16, - color: giftCardOrderModel.redeem == true ? AppThemeData.success400 : AppThemeData.danger300, - fontFamily: AppThemeData.semiBold, + color: + giftCardOrderModel.redeem == + true + ? AppThemeData + .success400 + : AppThemeData + .danger300, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w500, ), ), diff --git a/lib/screen_ui/multi_vendor_service/gift_card/redeem_gift_card_screen.dart b/lib/screen_ui/multi_vendor_service/gift_card/redeem_gift_card_screen.dart index 0096cda..04bb55f 100644 --- a/lib/screen_ui/multi_vendor_service/gift_card/redeem_gift_card_screen.dart +++ b/lib/screen_ui/multi_vendor_service/gift_card/redeem_gift_card_screen.dart @@ -11,8 +11,7 @@ import 'package:easy_localization/easy_localization.dart'; import '../../../controllers/theme_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; import '../dash_board_screens/dash_board_screen.dart'; @@ -28,7 +27,12 @@ class RedeemGiftCardScreen extends StatelessWidget { init: RedeemGiftCardController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: InkWell( onTap: () { FocusScope.of(context).unfocus(); @@ -40,11 +44,24 @@ class RedeemGiftCardScreen extends StatelessWidget { children: [ Text( "Redeem Gift Card".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( - "Enter your gift card code to enjoy discounts and special offers on your orders.".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + "Enter your gift card code to enjoy discounts and special offers on your orders." + .tr(), + style: TextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 20), TextFieldWidget( @@ -52,14 +69,20 @@ class RedeemGiftCardScreen extends StatelessWidget { controller: controller.giftCodeController.value, hintText: 'Enter gift code'.tr(), textInputType: TextInputType.number, - prefix: Padding(padding: const EdgeInsets.all(10), child: SvgPicture.asset("assets/icons/ic_gift_code.svg")), + prefix: Padding( + padding: const EdgeInsets.all(10), + child: SvgPicture.asset("assets/icons/ic_gift_code.svg"), + ), ), TextFieldWidget( title: 'Gift Pin'.tr(), controller: controller.giftPinController.value, hintText: 'Enter gift pin'.tr(), textInputType: TextInputType.number, - prefix: Padding(padding: const EdgeInsets.all(10), child: SvgPicture.asset("assets/icons/ic_gift_pin.svg")), + prefix: Padding( + padding: const EdgeInsets.all(10), + child: SvgPicture.asset("assets/icons/ic_gift_pin.svg"), + ), ), ], ), @@ -83,45 +106,73 @@ class RedeemGiftCardScreen extends StatelessWidget { ShowToastDialog.showToast("Please Enter Gift Pin".tr()); } else { ShowToastDialog.showLoader("Please wait...".tr()); - await FireStoreUtils.checkRedeemCode(controller.giftCodeController.value.text.replaceAll(" ", "")).then((value) async { + await FireStoreUtils.checkRedeemCode( + controller.giftCodeController.value.text.replaceAll( + " ", + "", + ), + ).then((value) async { if (value != null) { GiftCardsOrderModel giftCodeModel = value; if (giftCodeModel.redeem == true) { ShowToastDialog.closeLoader(); - ShowToastDialog.showToast("Gift voucher already redeemed".tr()); - } else if (giftCodeModel.giftPin != controller.giftPinController.value.text) { + ShowToastDialog.showToast( + "Gift voucher already redeemed".tr(), + ); + } else if (giftCodeModel.giftPin != + controller.giftPinController.value.text) { ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Gift Pin Invalid".tr()); - } else if (giftCodeModel.expireDate!.toDate().isBefore(DateTime.now())) { + } else if (giftCodeModel.expireDate!.toDate().isBefore( + DateTime.now(), + )) { ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Gift Voucher expire".tr()); } else { giftCodeModel.redeem = true; - WalletTransactionModel transactionModel = WalletTransactionModel( - id: Constant.getUuid(), - amount: double.parse(giftCodeModel.price.toString()), - date: Timestamp.now(), - paymentMethod: "Wallet", - transactionUser: "user", - userId: FireStoreUtils.getCurrentUid(), - isTopup: true, - note: "Gift Voucher", - paymentStatus: "success", - ); + WalletTransactionModel transactionModel = + WalletTransactionModel( + id: Constant.getUuid(), + amount: double.parse( + giftCodeModel.price.toString(), + ), + date: Timestamp.now(), + paymentMethod: "Wallet", + transactionUser: "user", + userId: FireStoreUtils.getCurrentUid(), + isTopup: true, + note: "Gift Voucher", + paymentStatus: "success", + ); - await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { + await FireStoreUtils.setWalletTransaction( + transactionModel, + ).then((value) async { if (value == true) { - await FireStoreUtils.updateUserWallet(amount: giftCodeModel.price.toString(), userId: FireStoreUtils.getCurrentUid()).then((value) async { - await FireStoreUtils.sendTopUpMail(paymentMethod: "Gift Voucher", amount: giftCodeModel.price.toString(), tractionId: transactionModel.id.toString()); - await FireStoreUtils.placeGiftCardOrder(giftCodeModel).then((value) { + await FireStoreUtils.updateUserWallet( + amount: giftCodeModel.price.toString(), + userId: FireStoreUtils.getCurrentUid(), + ).then((value) async { + await FireStoreUtils.sendTopUpMail( + paymentMethod: "Gift Voucher", + amount: giftCodeModel.price.toString(), + tractionId: transactionModel.id.toString(), + ); + await FireStoreUtils.placeGiftCardOrder( + giftCodeModel, + ).then((value) { ShowToastDialog.closeLoader(); if (Constant.walletSetting == true) { Get.offAll(const DashBoardScreen()); - DashBoardController controller = Get.put(DashBoardController()); + DashBoardController controller = Get.put( + DashBoardController(), + ); controller.selectedIndex.value = 2; } - ShowToastDialog.showToast("Voucher redeem successfully".tr()); + ShowToastDialog.showToast( + "Voucher redeem successfully".tr(), + ); }); }); } diff --git a/lib/screen_ui/multi_vendor_service/gift_card/select_gift_payment_screen.dart b/lib/screen_ui/multi_vendor_service/gift_card/select_gift_payment_screen.dart index 9297be8..7309bca 100644 --- a/lib/screen_ui/multi_vendor_service/gift_card/select_gift_payment_screen.dart +++ b/lib/screen_ui/multi_vendor_service/gift_card/select_gift_payment_screen.dart @@ -6,7 +6,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; import '../wallet_screen/wallet_screen.dart'; @@ -22,12 +22,22 @@ class SelectGiftPaymentScreen extends StatelessWidget { init: GiftCardController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Payment Option".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Payment Option".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -38,7 +48,12 @@ class SelectGiftPaymentScreen extends StatelessWidget { Text( "Preferred Payment".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), const SizedBox(height: 10), if (controller.walletSettingModel.value.isEnabled == true) @@ -47,17 +62,39 @@ class SelectGiftPaymentScreen extends StatelessWidget { children: [ Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 20, offset: Offset(0, 0), spreadRadius: 0)], + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadows: const [ + BoxShadow( + color: Color(0x07000000), + blurRadius: 20, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), ], ), @@ -67,40 +104,143 @@ class SelectGiftPaymentScreen extends StatelessWidget { Text( "Other Payment Options".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), ], ), Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 20, offset: Offset(0, 0), spreadRadius: 0)], + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadows: const [ + BoxShadow( + color: Color(0x07000000), + blurRadius: 20, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.flutterWaveModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.paytmModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.paytmModel.value.isEnabled == true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -110,7 +250,13 @@ class SelectGiftPaymentScreen extends StatelessWidget { ), ), bottomNavigationBar: Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), child: Padding( padding: const EdgeInsets.only(bottom: 20), @@ -121,38 +267,89 @@ class SelectGiftPaymentScreen extends StatelessWidget { textColor: AppThemeData.grey50, fontSizes: 16, onPress: () async { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.amountController.value.text, context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.amountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.amountController.value.text, + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.amountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.amountController.value.text), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.amountController.value.text, orderId: result.id); - } - }); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.amountController.value.text, + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: controller.amountController.value.text, + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } }, ), @@ -163,7 +360,12 @@ class SelectGiftPaymentScreen extends StatelessWidget { ); } - Obx cardDecoration(GiftCardController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + GiftCardController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -176,8 +378,16 @@ class SelectGiftPaymentScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -188,12 +398,32 @@ class SelectGiftPaymentScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: controller.userModel.value.walletAmount == null ? '0.0' : controller.userModel.value.walletAmount.toString()), + Constant.amountShow( + amount: + controller.userModel.value.walletAmount == null + ? '0.0' + : controller.userModel.value.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -202,14 +432,20 @@ class SelectGiftPaymentScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart b/lib/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart index 80ffc28..56c5e78 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart @@ -6,7 +6,7 @@ import 'package:customer/themes/responsive.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../widget/restaurant_image_view.dart'; import '../restaurant_details_screen/restaurant_details_screen.dart'; @@ -22,7 +22,12 @@ class CategoryRestaurantScreen extends StatelessWidget { init: CategoryRestaurantController(), builder: (controller) { return Scaffold( - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0), + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + centerTitle: false, + titleSpacing: 0, + ), body: controller.isLoading.value ? Constant.loader() @@ -34,33 +39,62 @@ class CategoryRestaurantScreen extends StatelessWidget { shrinkWrap: true, itemCount: controller.allNearestRestaurant.length, itemBuilder: (context, index) { - VendorModel vendorModel = controller.allNearestRestaurant[index]; + VendorModel vendorModel = + controller.allNearestRestaurant[index]; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Padding( padding: const EdgeInsets.only(bottom: 20), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), child: Stack( children: [ - RestaurantImageView(vendorModel: vendorModel), + RestaurantImageView( + vendorModel: vendorModel, + ), Container( - height: Responsive.height(20, context), - width: Responsive.width(100, context), + height: Responsive.height( + 20, + context, + ), + width: Responsive.width( + 100, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), + begin: const Alignment( + -0.00, + -1.00, + ), end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], ), ), ), @@ -68,28 +102,60 @@ class CategoryRestaurantScreen extends StatelessWidget { ), ), Transform.translate( - offset: Offset(Responsive.width(-3, context), Responsive.height(17.5, context)), + offset: Offset( + Responsive.width(-3, context), + Responsive.height(17.5, context), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, children: [ Visibility( - visible: (vendorModel.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (vendorModel.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true), child: Row( children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: BoxDecoration( - color: AppThemeData.success300, - borderRadius: BorderRadius.circular(120), // Optional + color: + AppThemeData + .success300, + borderRadius: + BorderRadius.circular( + 120, + ), // Optional ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg"), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + ), + const SizedBox( + width: 5, + ), Text( "Free Delivery".tr(), - style: TextStyle(fontSize: 14, color: AppThemeData.success600, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 14, + color: + AppThemeData + .success600, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, + ), ), ], ), @@ -100,22 +166,52 @@ class CategoryRestaurantScreen extends StatelessWidget { ), Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .primary600 + : AppThemeData + .primary50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -125,22 +221,52 @@ class CategoryRestaurantScreen extends StatelessWidget { const SizedBox(width: 6), Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.ecommerce600 : AppThemeData.ecommerce50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .ecommerce600 + : AppThemeData + .ecommerce50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_map_distance.svg", colorFilter: ColorFilter.mode(AppThemeData.ecommerce300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_map_distance.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .ecommerce300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.getDistance(lat1: vendorModel.latitude.toString(), lng1: vendorModel.longitude.toString(), lat2: Constant.selectedLocation.location!.latitude.toString(), lng2: Constant.selectedLocation.location!.longitude.toString())} ${Constant.distanceType}", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -154,9 +280,12 @@ class CategoryRestaurantScreen extends StatelessWidget { ), const SizedBox(height: 15), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( vendorModel.title.toString(), @@ -166,7 +295,10 @@ class CategoryRestaurantScreen extends StatelessWidget { fontSize: 18, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), Text( @@ -177,7 +309,10 @@ class CategoryRestaurantScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/home_screen/discount_restaurant_list_screen.dart b/lib/screen_ui/multi_vendor_service/home_screen/discount_restaurant_list_screen.dart index 05059fb..22ef568 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/discount_restaurant_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/discount_restaurant_list_screen.dart @@ -9,7 +9,7 @@ import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../restaurant_details_screen/restaurant_details_screen.dart'; @@ -25,13 +25,18 @@ class DiscountRestaurantListScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( controller.title.value, textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), body: @@ -47,24 +52,60 @@ class DiscountRestaurantListScreen extends StatelessWidget { CouponModel offerModel = controller.couponList[index]; return InkWell( onTap: () { - Get.to(RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Padding( padding: const EdgeInsets.only(bottom: 20), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), bottomLeft: Radius.circular(16)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(16), + ), child: Stack( children: [ - NetworkImageWidget(imageUrl: vendorModel.photo.toString(), fit: BoxFit.cover, height: Responsive.height(16, context), width: Responsive.width(28, context)), + NetworkImageWidget( + imageUrl: + vendorModel.photo.toString(), + fit: BoxFit.cover, + height: Responsive.height( + 16, + context, + ), + width: Responsive.width(28, context), + ), Container( - height: Responsive.height(16, context), + height: Responsive.height( + 16, + context, + ), width: Responsive.width(28, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(-0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), const Color(0xFF111827)]), + gradient: LinearGradient( + begin: const Alignment( + -0.00, + -1.00, + ), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], + ), ), ), Positioned( @@ -72,16 +113,37 @@ class DiscountRestaurantListScreen extends StatelessWidget { left: 10, child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(120), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), child: Text( "${offerModel.discountType == "Fix Price" ? Constant.currencyModel!.symbol : ""}${offerModel.discount}${offerModel.discountType == "Percentage" ? "% off".toUpperCase().tr() : " off".toUpperCase().tr()}", textAlign: TextAlign.start, maxLines: 1, - style: TextStyle(overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), ), ), @@ -91,9 +153,12 @@ class DiscountRestaurantListScreen extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ @@ -104,19 +169,45 @@ class DiscountRestaurantListScreen extends StatelessWidget { maxLines: 1, style: TextStyle( fontSize: 18, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, ), ), ), Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, + ), ), ], ), @@ -124,18 +215,33 @@ class DiscountRestaurantListScreen extends StatelessWidget { ), const SizedBox(height: 5), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Icon(Icons.location_on, size: 18, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600), + Icon( + Icons.location_on, + size: 18, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + ), const SizedBox(width: 5), Expanded( child: Text( - vendorModel.location.toString(), + vendorModel.location + .toString(), style: TextStyle( - fontFamily: AppThemeData.medium, + fontFamily: + AppThemeData.medium, fontWeight: FontWeight.w500, fontSize: 12, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey400, ), ), ), @@ -143,19 +249,45 @@ class DiscountRestaurantListScreen extends StatelessWidget { ), const SizedBox(height: 5), Container( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, child: DottedBorder( - options: RoundedRectDottedBorderOptions( - radius: const Radius.circular(6), - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - strokeWidth: 1, - ), + options: + RoundedRectDottedBorderOptions( + radius: + const Radius.circular( + 6, + ), + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + strokeWidth: 1, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 2, + ), child: Text( "${offerModel.code}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ), diff --git a/lib/screen_ui/multi_vendor_service/home_screen/home_screen.dart b/lib/screen_ui/multi_vendor_service/home_screen/home_screen.dart index f8c9af2..03adfec 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/home_screen.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/home_screen.dart @@ -29,7 +29,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:latlong2/latlong.dart' as location; import 'package:url_launcher/url_launcher.dart'; @@ -705,7 +705,8 @@ class HomeScreen extends StatelessWidget { children: [ Expanded( child: Text( - "New Arrivals".tr(), + "New Arrivals" + .tr(), textAlign: TextAlign .start, diff --git a/lib/screen_ui/multi_vendor_service/home_screen/home_screen_two.dart b/lib/screen_ui/multi_vendor_service/home_screen/home_screen_two.dart index 27ccd52..7641c69 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/home_screen_two.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/home_screen_two.dart @@ -28,7 +28,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:url_launcher/url_launcher.dart'; import '../../../controllers/theme_controller.dart'; import '../../../models/banner_model.dart'; @@ -57,11 +57,13 @@ class HomeScreenTwo extends StatelessWidget { init: FoodHomeController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: controller.isLoading.value ? Constant.loader() - : Constant.isZoneAvailable == false || controller.allNearestRestaurant.isEmpty + : Constant.isZoneAvailable == false || + controller.allNearestRestaurant.isEmpty ? Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -70,12 +72,30 @@ class HomeScreenTwo extends StatelessWidget { children: [ Image.asset("assets/images/location.gif", height: 120), const SizedBox(height: 12), - Text("No Store Found in Your Area".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "No Store Found in Your Area".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "Currently, there are no available store in your zone. Try changing your location to find nearby options.".tr(), + "Currently, there are no available store in your zone. Try changing your location to find nearby options." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -92,16 +112,21 @@ class HomeScreenTwo extends StatelessWidget { ), ) : Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: controller.isListView.value == false ? const MapView() : Column( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ @@ -109,98 +134,215 @@ class HomeScreenTwo extends StatelessWidget { onTap: () { Get.back(); }, - child: Icon(Icons.arrow_back, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, size: 20), + child: Icon( + Icons.arrow_back, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + size: 20, + ), ), const SizedBox(width: 10), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Constant.userModel == null ? InkWell( onTap: () { - Get.offAll(const LoginScreen()); + Get.offAll( + const LoginScreen(), + ); }, child: Text( "Login".tr(), - textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 12), + textAlign: + TextAlign.center, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 12, + ), ), ) : Text( - Constant.userModel!.fullName(), - textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 12), + Constant.userModel! + .fullName(), + textAlign: + TextAlign.center, + style: TextStyle( + fontFamily: + AppThemeData.medium, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 12, + ), ), InkWell( onTap: () async { - if (Constant.userModel != null) { - Get.to(AddressListScreen())!.then((value) { + if (Constant.userModel != + null) { + Get.to( + AddressListScreen(), + )!.then((value) { if (value != null) { - ShippingAddress shippingAddress = value; - Constant.selectedLocation = shippingAddress; + ShippingAddress + shippingAddress = + value; + Constant.selectedLocation = + shippingAddress; controller.getData(); } }); } else { Constant.checkPermission( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait..." + .tr(), + ); // ✅ declare once for whole method - ShippingAddress shippingAddress = ShippingAddress(); + ShippingAddress + shippingAddress = + ShippingAddress(); try { await Geolocator.requestPermission(); await Geolocator.getCurrentPosition(); ShowToastDialog.closeLoader(); - if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); - if (result != null) { - final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; - final address = firstPlace.address; + if (Constant + .selectedMapType == + 'osm') { + final result = + await Get.to( + () => + MapPickerPage(), + ); + if (result != + null) { + final firstPlace = + result; + final lat = + firstPlace + .coordinates + .latitude; + final lng = + firstPlace + .coordinates + .longitude; + final address = + firstPlace + .address; - shippingAddress.addressAs = "Home"; - shippingAddress.locality = address.toString(); - shippingAddress.location = UserLocation(latitude: lat, longitude: lng); - Constant.selectedLocation = shippingAddress; - controller.getData(); + shippingAddress + .addressAs = + "Home"; + shippingAddress + .locality = + address + .toString(); + shippingAddress + .location = + UserLocation( + latitude: + lat, + longitude: + lng, + ); + Constant.selectedLocation = + shippingAddress; + controller + .getData(); Get.back(); } } else { - Get.to(LocationPickerScreen())!.then((value) async { - if (value != null) { - SelectedLocationModel selectedLocationModel = value; + Get.to( + LocationPickerScreen(), + )!.then(( + value, + ) async { + if (value != + null) { + SelectedLocationModel + selectedLocationModel = + value; - shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation( - latitude: selectedLocationModel.latLng!.latitude, - longitude: selectedLocationModel.latLng!.longitude, + shippingAddress + .addressAs = + "Home"; + shippingAddress + .location = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, ); - shippingAddress.locality = "Picked from Map"; // You can reverse-geocode + shippingAddress + .locality = + "Picked from Map"; // You can reverse-geocode - Constant.selectedLocation = shippingAddress; - controller.getData(); + Constant.selectedLocation = + shippingAddress; + controller + .getData(); } }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { - Placemark placeMark = valuePlaceMaker[0]; - shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118); - String currentLocation = + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then(( + valuePlaceMaker, + ) { + Placemark + placeMark = + valuePlaceMaker[0]; + shippingAddress + .addressAs = + "Home"; + shippingAddress + .location = + UserLocation( + latitude: + 19.228825, + longitude: + 72.854118, + ); + String + currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; - shippingAddress.locality = currentLocation; + shippingAddress + .locality = + currentLocation; }); - Constant.selectedLocation = shippingAddress; + Constant.selectedLocation = + shippingAddress; ShowToastDialog.closeLoader(); - controller.getData(); + controller + .getData(); } }, context: context, @@ -209,19 +351,36 @@ class HomeScreenTwo extends StatelessWidget { }, child: Text.rich( maxLines: 1, - overflow: TextOverflow.ellipsis, + overflow: + TextOverflow.ellipsis, TextSpan( children: [ TextSpan( - text: Constant.selectedLocation.getFullAddress(), + text: + Constant + .selectedLocation + .getFullAddress(), style: TextStyle( - fontFamily: AppThemeData.medium, - overflow: TextOverflow.ellipsis, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: + AppThemeData + .medium, + overflow: + TextOverflow + .ellipsis, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, fontSize: 14, ), ), - WidgetSpan(child: SvgPicture.asset("assets/icons/ic_down.svg")), + WidgetSpan( + child: SvgPicture.asset( + "assets/icons/ic_down.svg", + ), + ), ], ), ), @@ -232,16 +391,28 @@ class HomeScreenTwo extends StatelessWidget { const SizedBox(width: 5), InkWell( onTap: () async { - (await Get.to(const CartScreen())); + (await Get.to( + const CartScreen(), + )); controller.getCartData(); }, child: ClipOval( child: Container( - padding: const EdgeInsets.all(8.0), - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + padding: const EdgeInsets.all( + 8.0, + ), + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, child: SvgPicture.asset( "assets/icons/ic_shoping_cart.svg", - colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey50 : AppThemeData.grey900, BlendMode.srcIn), + colorFilter: ColorFilter.mode( + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + BlendMode.srcIn, + ), ), ), ), @@ -251,16 +422,39 @@ class HomeScreenTwo extends StatelessWidget { const SizedBox(height: 10), InkWell( onTap: () { - Get.to(const SearchScreen(), arguments: {"vendorList": controller.allNearestRestaurant}); + Get.to( + const SearchScreen(), + arguments: { + "vendorList": + controller + .allNearestRestaurant, + }, + ); }, child: TextFieldWidget( hintText: - Constant.sectionConstantModel?.name?.toLowerCase().contains('restaurants') == true - ? 'Search the dish, foo and more...'.tr() - : 'Search the store, item and more...'.tr(), + Constant + .sectionConstantModel + ?.name + ?.toLowerCase() + .contains( + 'restaurants', + ) == + true + ? 'Search the dish, foo and more...' + .tr() + : 'Search the store, item and more...' + .tr(), controller: null, enable: false, - prefix: Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: SvgPicture.asset("assets/icons/ic_search.svg")), + prefix: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), + child: SvgPicture.asset( + "assets/icons/ic_search.svg", + ), + ), ), ), const SizedBox(height: 5), @@ -271,64 +465,185 @@ class HomeScreenTwo extends StatelessWidget { child: SingleChildScrollView( child: Column( children: [ - controller.bannerModel.isEmpty ? const SizedBox() : Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: BannerView(controller: controller)), + controller.bannerModel.isEmpty + ? const SizedBox() + : Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), + child: BannerView( + controller: controller, + ), + ), const SizedBox(height: 20), - Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: CategoryView(controller: controller)), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), + child: CategoryView( + controller: controller, + ), + ), controller.couponRestaurantList.isEmpty ? const SizedBox() - : Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: Column(children: [const SizedBox(height: 20), OfferView(controller: controller)])), - controller.storyList.isEmpty || Constant.storyEnable == false + : Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), + child: Column( + children: [ + const SizedBox(height: 20), + OfferView( + controller: controller, + ), + ], + ), + ), + controller.storyList.isEmpty || + Constant.storyEnable == false ? const SizedBox() - : Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: Column(children: [const SizedBox(height: 20), StoryView(controller: controller)])), + : Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), + child: Column( + children: [ + const SizedBox(height: 20), + StoryView( + controller: controller, + ), + ], + ), + ), Visibility( - visible: Constant.isEnableAdsFeature == true, + visible: + Constant.isEnableAdsFeature == + true, child: - controller.advertisementList.isEmpty + controller + .advertisementList + .isEmpty ? const SizedBox() : Column( children: [ - const SizedBox(height: 20), + const SizedBox( + height: 20, + ), Container( - margin: const EdgeInsets.symmetric(horizontal: 16), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: AppThemeData.primary300.withAlpha(40)), + margin: + const EdgeInsets.symmetric( + horizontal: 16, + ), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 20, + ), + color: AppThemeData + .primary300 + .withAlpha(40), + ), child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Row( children: [ Expanded( child: Text( - "Highlights for you".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + "Highlights for you" + .tr(), + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + fontSize: + 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), InkWell( onTap: () { - Get.to(AllAdvertisementScreen())?.then((value) { - controller.getFavouriteRestaurant(); + Get.to( + AllAdvertisementScreen(), + )?.then(( + value, + ) { + controller + .getFavouriteRestaurant(); }); }, child: Text( - "See all".tr(), - textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + "See all" + .tr(), + textAlign: + TextAlign + .center, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ], ), - const SizedBox(height: 16), + const SizedBox( + height: 16, + ), SizedBox( height: 220, child: ListView.builder( - physics: const BouncingScrollPhysics(), - scrollDirection: Axis.horizontal, - itemCount: controller.advertisementList.length >= 10 ? 10 : controller.advertisementList.length, - padding: EdgeInsets.all(0), - itemBuilder: (BuildContext context, int index) { - return AdvertisementHomeCard(controller: controller, model: controller.advertisementList[index]); + physics: + const BouncingScrollPhysics(), + scrollDirection: + Axis.horizontal, + itemCount: + controller.advertisementList.length >= + 10 + ? 10 + : controller + .advertisementList + .length, + padding: + EdgeInsets.all( + 0, + ), + itemBuilder: ( + BuildContext + context, + int index, + ) { + return AdvertisementHomeCard( + controller: + controller, + model: + controller + .advertisementList[index], + ); }, ), ), @@ -338,7 +653,16 @@ class HomeScreenTwo extends StatelessWidget { ], ), ), - controller.allNearestRestaurant.isEmpty ? const SizedBox() : Column(children: [const SizedBox(height: 20), RestaurantView(controller: controller)]), + controller.allNearestRestaurant.isEmpty + ? const SizedBox() + : Column( + children: [ + const SizedBox(height: 20), + RestaurantView( + controller: controller, + ), + ], + ), ], ), ), @@ -346,18 +670,29 @@ class HomeScreenTwo extends StatelessWidget { ], ), ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, + floatingActionButtonLocation: + FloatingActionButtonLocation.centerFloat, floatingActionButton: Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, borderRadius: const BorderRadius.all(Radius.circular(30))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + borderRadius: const BorderRadius.all(Radius.circular(30)), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, borderRadius: const BorderRadius.all(Radius.circular(30))), + decoration: BoxDecoration( + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + borderRadius: const BorderRadius.all(Radius.circular(30)), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( children: [ InkWell( @@ -366,12 +701,22 @@ class HomeScreenTwo extends StatelessWidget { }, child: ClipOval( child: Container( - decoration: BoxDecoration(color: controller.isListView.value ? AppThemeData.primary300 : null), + decoration: BoxDecoration( + color: + controller.isListView.value + ? AppThemeData.primary300 + : null, + ), child: Padding( padding: const EdgeInsets.all(8.0), child: SvgPicture.asset( "assets/icons/ic_view_grid_list.svg", - colorFilter: ColorFilter.mode(controller.isListView.value ? AppThemeData.grey50 : AppThemeData.grey500, BlendMode.srcIn), + colorFilter: ColorFilter.mode( + controller.isListView.value + ? AppThemeData.grey50 + : AppThemeData.grey500, + BlendMode.srcIn, + ), ), ), ), @@ -384,12 +729,22 @@ class HomeScreenTwo extends StatelessWidget { }, child: ClipOval( child: Container( - decoration: BoxDecoration(color: controller.isListView.value == false ? AppThemeData.primary300 : null), + decoration: BoxDecoration( + color: + controller.isListView.value == false + ? AppThemeData.primary300 + : null, + ), child: Padding( padding: const EdgeInsets.all(8.0), child: SvgPicture.asset( "assets/icons/ic_map_draw.svg", - colorFilter: ColorFilter.mode(controller.isListView.value == false ? AppThemeData.grey50 : AppThemeData.grey500, BlendMode.srcIn), + colorFilter: ColorFilter.mode( + controller.isListView.value == false + ? AppThemeData.grey50 + : AppThemeData.grey500, + BlendMode.srcIn, + ), ), ), ), @@ -406,10 +761,23 @@ class HomeScreenTwo extends StatelessWidget { }, child: ClipOval( child: Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + ), child: Padding( padding: const EdgeInsets.all(10), - child: SvgPicture.asset("assets/icons/ic_scan_code.svg", colorFilter: ColorFilter.mode(isDark ? AppThemeData.grey400 : AppThemeData.grey500, BlendMode.srcIn)), + child: SvgPicture.asset( + "assets/icons/ic_scan_code.svg", + colorFilter: ColorFilter.mode( + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + BlendMode.srcIn, + ), + ), ), ), ), @@ -421,15 +789,30 @@ class HomeScreenTwo extends StatelessWidget { value: controller.selectedOrderTypeValue.value.tr(), icon: const Icon(Icons.keyboard_arrow_down), items: - ['Delivery'.tr(), 'TakeAway'.tr()].map((String value) { + ['Delivery'.tr(), 'TakeAway'.tr()].map(( + String value, + ) { return DropdownMenuItem( value: value, - child: Text(value.tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + child: Text( + value.tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), + ), ); }).toList(), onChanged: (value) async { if (cartItem.isEmpty) { - await Preferences.setString(Preferences.foodDeliveryType, value!); + await Preferences.setString( + Preferences.foodDeliveryType, + value!, + ); controller.selectedOrderTypeValue.value = value; controller.getData(); } else { @@ -438,11 +821,16 @@ class HomeScreenTwo extends StatelessWidget { builder: (BuildContext context) { return CustomDialogBox( title: "Alert".tr(), - descriptions: "Do you really want to change the delivery option? Your cart will be empty.".tr(), + descriptions: + "Do you really want to change the delivery option? Your cart will be empty." + .tr(), positiveString: "Ok".tr(), negativeString: "Cancel".tr(), positiveClick: () async { - await Preferences.setString(Preferences.foodDeliveryType, value!); + await Preferences.setString( + Preferences.foodDeliveryType, + value!, + ); controller.selectedOrderTypeValue.value = value; controller.getData(); DatabaseHelper.instance.deleteAllCartProducts(); @@ -480,7 +868,10 @@ class CategoryView extends StatelessWidget { final themeController = Get.find(); final isDark = themeController.isDark.value; return Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( @@ -494,7 +885,19 @@ class CategoryView extends StatelessWidget { children: [ Row( children: [ - Expanded(child: Text("Our Categories".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18))), + Expanded( + child: Text( + "Our Categories".tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 18, + ), + ), + ), InkWell( onTap: () { Get.to(const ViewAllCategoryScreen()); @@ -502,15 +905,28 @@ class CategoryView extends StatelessWidget { child: Text( "See all".tr(), textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 14), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 14, + ), ), ), ], ), GradientText( 'Best Servings Food'.tr(), - style: TextStyle(fontSize: 24, fontFamily: 'Inter Tight', fontWeight: FontWeight.w800), - gradient: LinearGradient(colors: [Color(0xFF3961F1), Color(0xFF11D0EA)]), + style: TextStyle( + fontSize: 24, + fontFamily: 'Inter Tight', + fontWeight: FontWeight.w800, + ), + gradient: LinearGradient( + colors: [Color(0xFF3961F1), Color(0xFF11D0EA)], + ), ), ], ), @@ -518,23 +934,52 @@ class CategoryView extends StatelessWidget { const SizedBox(height: 10), GridView.builder( padding: EdgeInsets.zero, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 5 / 6), - itemCount: controller.vendorCategoryModel.length >= 8 ? 8 : controller.vendorCategoryModel.length, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + childAspectRatio: 5 / 6, + ), + itemCount: + controller.vendorCategoryModel.length >= 8 + ? 8 + : controller.vendorCategoryModel.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { - VendorCategoryModel vendorCategoryModel = controller.vendorCategoryModel[index]; + VendorCategoryModel vendorCategoryModel = + controller.vendorCategoryModel[index]; return InkWell( onTap: () { - Get.to(const CategoryRestaurantScreen(), arguments: {"vendorCategoryModel": vendorCategoryModel, "dineIn": false}); + Get.to( + const CategoryRestaurantScreen(), + arguments: { + "vendorCategoryModel": vendorCategoryModel, + "dineIn": false, + }, + ); }, child: Column( children: [ - ClipOval(child: SizedBox(width: 60, height: 60, child: NetworkImageWidget(imageUrl: vendorCategoryModel.photo.toString(), fit: BoxFit.cover))), + ClipOval( + child: SizedBox( + width: 60, + height: 60, + child: NetworkImageWidget( + imageUrl: vendorCategoryModel.photo.toString(), + fit: BoxFit.cover, + ), + ), + ), Text( "${vendorCategoryModel.title}", textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 12), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 12, + ), ), ], ), @@ -558,7 +1003,10 @@ class OfferView extends StatelessWidget { final themeController = Get.find(); final isDark = themeController.isDark.value; return Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( @@ -572,26 +1020,55 @@ class OfferView extends StatelessWidget { children: [ Row( children: [ - Expanded(child: Text("Large Discounts".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18))), + Expanded( + child: Text( + "Large Discounts".tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 18, + ), + ), + ), InkWell( onTap: () { Get.to( const DiscountRestaurantListScreen(), - arguments: {"vendorList": controller.couponRestaurantList, "couponList": controller.couponList, "title": "Discounts Restaurants"}, + arguments: { + "vendorList": controller.couponRestaurantList, + "couponList": controller.couponList, + "title": "Discounts Restaurants", + }, ); }, child: Text( "See all".tr(), textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 14), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 14, + ), ), ), ], ), GradientText( 'Save Upto 50% Off'.tr(), - style: TextStyle(fontSize: 24, fontFamily: 'Inter Tight', fontWeight: FontWeight.w800), - gradient: LinearGradient(colors: [Color(0xFF39F1C5), Color(0xFF97EA11)]), + style: TextStyle( + fontSize: 24, + fontFamily: 'Inter Tight', + fontWeight: FontWeight.w800, + ), + gradient: LinearGradient( + colors: [Color(0xFF39F1C5), Color(0xFF97EA11)], + ), ), ], ), @@ -604,47 +1081,82 @@ class OfferView extends StatelessWidget { shrinkWrap: true, scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), - itemCount: controller.couponRestaurantList.length >= 15 ? 15 : controller.couponRestaurantList.length, + itemCount: + controller.couponRestaurantList.length >= 15 + ? 15 + : controller.couponRestaurantList.length, itemBuilder: (context, index) { - VendorModel vendorModel = controller.couponRestaurantList[index]; + VendorModel vendorModel = + controller.couponRestaurantList[index]; CouponModel offerModel = controller.couponList[index]; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Padding( padding: const EdgeInsets.only(right: 10), child: SizedBox( width: Responsive.width(34, context), child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: Stack( children: [ - NetworkImageWidget(imageUrl: vendorModel.photo.toString(), fit: BoxFit.cover, height: Responsive.height(100, context), width: Responsive.width(100, context)), + NetworkImageWidget( + imageUrl: vendorModel.photo.toString(), + fit: BoxFit.cover, + height: Responsive.height(100, context), + width: Responsive.width(100, context), + ), Container( decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(-0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), AppThemeData.grey900]), + gradient: LinearGradient( + begin: const Alignment(-0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + AppThemeData.grey900, + ], + ), ), ), Align( alignment: Alignment.bottomCenter, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Text( vendorModel.title.toString(), textAlign: TextAlign.start, maxLines: 1, - style: TextStyle(fontSize: 18, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + fontSize: 18, + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), const SizedBox(height: 5), RoundedButtonFill( title: "${offerModel.discountType == "Fix Price" ? Constant.currencyModel!.symbol : ""}${offerModel.discount}${offerModel.discountType == "Percentage" ? "% off".tr() : "off".tr()}", - color: Colors.primaries[Random().nextInt(Colors.primaries.length)], + color: + Colors.primaries[Random().nextInt( + Colors.primaries.length, + )], textColor: AppThemeData.grey50, width: 20, height: 3.5, @@ -696,17 +1208,30 @@ class BannerView extends StatelessWidget { onTap: () async { if (bannerModel.redirect_type == "store") { ShowToastDialog.showLoader("Please wait...".tr()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(bannerModel.redirect_id.toString()); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + bannerModel.redirect_id.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "product") { ShowToastDialog.showLoader("Please wait...".tr()); - ProductModel? productModel = await FireStoreUtils.getProductById(bannerModel.redirect_id.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(productModel!.vendorID.toString()); + ProductModel? productModel = + await FireStoreUtils.getProductById( + bannerModel.redirect_id.toString(), + ); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + productModel!.vendorID.toString(), + ); ShowToastDialog.closeLoader(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); } else if (bannerModel.redirect_type == "external_link") { final uri = Uri.parse(bannerModel.redirect_id.toString()); if (await canLaunchUrl(uri)) { @@ -718,7 +1243,13 @@ class BannerView extends StatelessWidget { }, child: Padding( padding: const EdgeInsets.only(right: 14), - child: ClipRRect(borderRadius: const BorderRadius.all(Radius.circular(12)), child: NetworkImageWidget(imageUrl: bannerModel.photo.toString(), fit: BoxFit.cover)), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: NetworkImageWidget( + imageUrl: bannerModel.photo.toString(), + fit: BoxFit.cover, + ), + ), ), ); }, @@ -738,7 +1269,13 @@ class StoryView extends StatelessWidget { final isDark = themeController.isDark.value; return Container( height: Responsive.height(32, context), - decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(20)), image: DecorationImage(image: AssetImage("assets/images/story_bg.png"), fit: BoxFit.cover)), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + image: DecorationImage( + image: AssetImage("assets/images/story_bg.png"), + fit: BoxFit.cover, + ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -747,11 +1284,33 @@ class StoryView extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row(children: [Expanded(child: Text("Stories".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 18)))]), + Row( + children: [ + Expanded( + child: Text( + "Stories".tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontSize: 18, + ), + ), + ), + ], + ), GradientText( 'Best Food Stories Ever'.tr(), - style: TextStyle(fontSize: 24, fontFamily: 'Inter Tight', fontWeight: FontWeight.w800), - gradient: LinearGradient(colors: [Color(0xFFF1C839), Color(0xFFEA1111)]), + style: TextStyle( + fontSize: 24, + fontFamily: 'Inter Tight', + fontWeight: FontWeight.w800, + ), + gradient: LinearGradient( + colors: [Color(0xFFF1C839), Color(0xFFEA1111)], + ), ), ], ), @@ -769,56 +1328,116 @@ class StoryView extends StatelessWidget { padding: const EdgeInsets.only(right: 10), child: InkWell( onTap: () { - Navigator.of(context).push(MaterialPageRoute(builder: (context) => MoreStories(storyList: controller.storyList, index: index))); + Navigator.of(context).push( + MaterialPageRoute( + builder: + (context) => MoreStories( + storyList: controller.storyList, + index: index, + ), + ), + ); }, child: SizedBox( width: 134, child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: Stack( children: [ - NetworkImageWidget(imageUrl: storyModel.videoThumbnail.toString(), fit: BoxFit.cover, height: Responsive.height(100, context), width: Responsive.width(100, context)), + NetworkImageWidget( + imageUrl: storyModel.videoThumbnail.toString(), + fit: BoxFit.cover, + height: Responsive.height(100, context), + width: Responsive.width(100, context), + ), Container(color: Colors.black.withOpacity(0.30)), Padding( - padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 5, + vertical: 8, + ), child: FutureBuilder( - future: FireStoreUtils.getVendorById(storyModel.vendorID.toString()), + future: FireStoreUtils.getVendorById( + storyModel.vendorID.toString(), + ), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot.connectionState == + ConnectionState.waiting) { return Constant.loader(); } else { if (snapshot.hasError) { - return Center(child: Text('${"Error".tr()}: ${snapshot.error}')); + return Center( + child: Text( + '${"Error".tr()}: ${snapshot.error}', + ), + ); } else if (snapshot.data == null) { return const SizedBox(); } else { - VendorModel vendorModel = snapshot.data!; + VendorModel vendorModel = + snapshot.data!; return Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - ClipOval(child: NetworkImageWidget(imageUrl: vendorModel.photo.toString(), width: 30, height: 30, fit: BoxFit.cover)), + ClipOval( + child: NetworkImageWidget( + imageUrl: + vendorModel.photo + .toString(), + width: 30, + height: 30, + fit: BoxFit.cover, + ), + ), const SizedBox(width: 4), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - vendorModel.title.toString(), + vendorModel.title + .toString(), textAlign: TextAlign.center, maxLines: 1, - style: const TextStyle(color: Colors.white, fontSize: 12, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w700), + style: const TextStyle( + color: Colors.white, + fontSize: 12, + overflow: + TextOverflow.ellipsis, + fontWeight: + FontWeight.w700, + ), ), Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg"), + SvgPicture.asset( + "assets/icons/ic_star.svg", + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount.toString(), reviewSum: vendorModel.reviewsSum!.toStringAsFixed(0))} ${'reviews'.tr()}", - textAlign: TextAlign.center, + textAlign: + TextAlign.center, maxLines: 1, - style: const TextStyle(color: AppThemeData.warning300, fontSize: 10, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w700), + style: const TextStyle( + color: + AppThemeData + .warning300, + fontSize: 10, + overflow: + TextOverflow + .ellipsis, + fontWeight: + FontWeight.w700, + ), ), ], ), @@ -870,15 +1489,38 @@ class RestaurantView extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), child: Row( children: [ - Expanded(child: Text("Best Restaurants".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18))), + Expanded( + child: Text( + "Best Restaurants".tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontSize: 18, + ), + ), + ), InkWell( onTap: () { - Get.to(const RestaurantListScreen(), arguments: {"vendorList": controller.allNearestRestaurant, "title": "Best Restaurants"}); + Get.to( + const RestaurantListScreen(), + arguments: { + "vendorList": controller.allNearestRestaurant, + "title": "Best Restaurants", + }, + ); }, child: Text( "See all".tr(), textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 14), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontSize: 14, + ), ), ), ], @@ -894,36 +1536,65 @@ class RestaurantView extends StatelessWidget { scrollDirection: Axis.vertical, itemCount: controller.allNearestRestaurant.length, itemBuilder: (BuildContext context, int index) { - VendorModel vendorModel = controller.allNearestRestaurant[index]; + VendorModel vendorModel = + controller.allNearestRestaurant[index]; List tempList = []; List discountAmountTempList = []; for (var element in controller.couponList) { - if (vendorModel.id == element.vendorID && element.expiresAt!.toDate().isAfter(DateTime.now())) { + if (vendorModel.id == element.vendorID && + element.expiresAt!.toDate().isAfter(DateTime.now())) { tempList.add(element); - discountAmountTempList.add(double.parse(element.discount.toString())); + discountAmountTempList.add( + double.parse(element.discount.toString()), + ); } } return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Padding( padding: const EdgeInsets.only(bottom: 20), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: const BorderRadius.all( + Radius.circular(16), + ), child: Stack( children: [ - NetworkImageWidget(height: Responsive.height(14, context), width: Responsive.width(30, context), imageUrl: vendorModel.photo.toString(), fit: BoxFit.cover), + NetworkImageWidget( + height: Responsive.height(14, context), + width: Responsive.width(30, context), + imageUrl: vendorModel.photo.toString(), + fit: BoxFit.cover, + ), Container( height: Responsive.height(14, context), width: Responsive.width(30, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(-0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), const Color(0xFF111827)]), + gradient: LinearGradient( + begin: const Alignment(-0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], + ), ), ), discountAmountTempList.isEmpty @@ -933,31 +1604,47 @@ class RestaurantView extends StatelessWidget { left: 0, right: 0, child: Padding( - padding: const EdgeInsets.only(bottom: 10), + padding: const EdgeInsets.only( + bottom: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Text( "Upto".tr(), textAlign: TextAlign.center, maxLines: 1, style: TextStyle( - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.regular, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.regular, fontWeight: FontWeight.w900, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, ), ), Text( - discountAmountTempList.reduce(min).toString() + "% OFF".tr(), + discountAmountTempList + .reduce(min) + .toString() + + "% OFF".tr(), textAlign: TextAlign.center, maxLines: 1, style: TextStyle( fontSize: 18, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, ), ), ], @@ -977,7 +1664,15 @@ class RestaurantView extends StatelessWidget { vendorModel.title.toString(), textAlign: TextAlign.start, maxLines: 1, - style: TextStyle(fontSize: 18, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontSize: 18, + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( vendorModel.location.toString(), @@ -987,7 +1682,10 @@ class RestaurantView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), const SizedBox(height: 5), @@ -996,18 +1694,31 @@ class RestaurantView extends StatelessWidget { child: Row( children: [ Visibility( - visible: (vendorModel.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (vendorModel.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg", width: 18), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + width: 18, + ), const SizedBox(width: 5), Text( "Free Delivery".tr(), style: TextStyle( - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey400, ), ), const SizedBox(width: 10), @@ -1017,8 +1728,18 @@ class RestaurantView extends StatelessWidget { Row( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: SvgPicture.asset("assets/icons/ic_star.svg", width: 18, colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), + child: SvgPicture.asset( + "assets/icons/ic_star.svg", + width: 18, + colorFilter: ColorFilter.mode( + AppThemeData.primary300, + BlendMode.srcIn, + ), + ), ), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount.toString(), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", @@ -1028,7 +1749,10 @@ class RestaurantView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), ], @@ -1036,8 +1760,18 @@ class RestaurantView extends StatelessWidget { Row( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: Icon(Icons.circle, size: 5, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Icon( + Icons.circle, + size: 5, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), Text( "${Constant.getDistance(lat1: vendorModel.latitude.toString(), lng1: vendorModel.longitude.toString(), lat2: Constant.selectedLocation.location!.latitude.toString(), lng2: Constant.selectedLocation.location!.longitude.toString())} ${Constant.distanceType}", @@ -1047,7 +1781,10 @@ class RestaurantView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart b/lib/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart index d6282a4..0b80cd0 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart @@ -8,8 +8,7 @@ import 'package:easy_localization/easy_localization.dart'; import '../../../controllers/theme_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../../../widget/restaurant_image_view.dart'; import '../restaurant_details_screen/restaurant_details_screen.dart'; @@ -26,13 +25,18 @@ class RestaurantListScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( controller.title.value, textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), body: @@ -44,35 +48,64 @@ class RestaurantListScreen extends StatelessWidget { shrinkWrap: true, itemCount: controller.vendorSearchList.length, itemBuilder: (context, index) { - VendorModel vendorModel = controller.vendorSearchList[index]; + VendorModel vendorModel = + controller.vendorSearchList[index]; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel})?.then((v) { + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + )?.then((v) { controller.getFavouriteRestaurant(); }); }, child: Padding( padding: const EdgeInsets.only(bottom: 20), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), child: Stack( children: [ - RestaurantImageView(vendorModel: vendorModel), + RestaurantImageView( + vendorModel: vendorModel, + ), Container( - height: Responsive.height(20, context), - width: Responsive.width(100, context), + height: Responsive.height( + 20, + context, + ), + width: Responsive.width( + 100, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), + begin: const Alignment( + -0.00, + -1.00, + ), end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], ), ), ), @@ -81,21 +114,60 @@ class RestaurantListScreen extends StatelessWidget { top: 10, child: InkWell( onTap: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == vendorModel.id).isNotEmpty) { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: vendorModel.id, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.removeWhere((item) => item.restaurantId == vendorModel.id); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); + if (controller.favouriteList + .where( + (p0) => + p0.restaurantId == + vendorModel.id, + ) + .isNotEmpty) { + FavouriteModel + favouriteModel = FavouriteModel( + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList + .removeWhere( + (item) => + item.restaurantId == + vendorModel.id, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: vendorModel.id, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); + FavouriteModel + favouriteModel = FavouriteModel( + restaurantId: + vendorModel.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList + .add(favouriteModel); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } }, child: Obx( () => - controller.favouriteList.where((p0) => p0.restaurantId == vendorModel.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteList + .where( + (p0) => + p0.restaurantId == + vendorModel + .id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), ), @@ -103,28 +175,60 @@ class RestaurantListScreen extends StatelessWidget { ), ), Transform.translate( - offset: Offset(Responsive.width(-3, context), Responsive.height(17.5, context)), + offset: Offset( + Responsive.width(-3, context), + Responsive.height(17.5, context), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, children: [ Visibility( - visible: (vendorModel.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (vendorModel.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true), child: Row( children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: BoxDecoration( - color: AppThemeData.success300, - borderRadius: BorderRadius.circular(120), // Optional + color: + AppThemeData + .success300, + borderRadius: + BorderRadius.circular( + 120, + ), // Optional ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg"), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + ), + const SizedBox( + width: 5, + ), Text( "Free Delivery".tr(), - style: TextStyle(fontSize: 14, color: AppThemeData.carRent600, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 14, + color: + AppThemeData + .carRent600, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, + ), ), ], ), @@ -134,22 +238,51 @@ class RestaurantListScreen extends StatelessWidget { ), ), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .primary600 + : AppThemeData + .primary50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -157,22 +290,51 @@ class RestaurantListScreen extends StatelessWidget { ), const SizedBox(width: 6), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.ecommerce600 : AppThemeData.ecommerce50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .ecommerce600 + : AppThemeData + .ecommerce50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_map_distance.svg", colorFilter: ColorFilter.mode(AppThemeData.ecommerce300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_map_distance.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .ecommerce300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.getDistance(lat1: vendorModel.latitude.toString(), lng1: vendorModel.longitude.toString(), lat2: Constant.selectedLocation.location!.latitude.toString(), lng2: Constant.selectedLocation.location!.longitude.toString())} ${Constant.distanceType}", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -185,9 +347,12 @@ class RestaurantListScreen extends StatelessWidget { ), const SizedBox(height: 15), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( vendorModel.title.toString(), @@ -197,7 +362,10 @@ class RestaurantListScreen extends StatelessWidget { fontSize: 18, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), Text( @@ -208,7 +376,10 @@ class RestaurantListScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey400, ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/home_screen/story_view.dart b/lib/screen_ui/multi_vendor_service/home_screen/story_view.dart index 5536d29..6850c56 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/story_view.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/story_view.dart @@ -8,7 +8,7 @@ import 'package:customer/widget/story_view/utils.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../../../widget/story_view/widgets/story_view.dart'; import '../restaurant_details_screen/restaurant_details_screen.dart'; @@ -71,9 +71,15 @@ class MoreStoriesState extends State { StoryView( key: ValueKey(widget.index), storyItems: - List.generate(widget.storyList[widget.index].videoUrl.length, (i) { - return StoryItem.pageVideo(widget.storyList[widget.index].videoUrl[i], controller: storyController); - }).toList(), + List.generate( + widget.storyList[widget.index].videoUrl.length, + (i) { + return StoryItem.pageVideo( + widget.storyList[widget.index].videoUrl[i], + controller: storyController, + ); + }, + ).toList(), onComplete: () { debugPrint("--------->"); debugPrint(widget.storyList.length.toString()); @@ -96,15 +102,23 @@ class MoreStoriesState extends State { }, ), Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top + 30, left: 16, right: 16), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top + 30, + left: 16, + right: 16, + ), child: FutureBuilder( - future: FireStoreUtils.getVendorById(widget.storyList[widget.index].vendorID.toString()), + future: FireStoreUtils.getVendorById( + widget.storyList[widget.index].vendorID.toString(), + ), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return SizedBox(); } else { if (snapshot.hasError) { - return Center(child: Text('${"Error".tr()}: ${snapshot.error}')); + return Center( + child: Text('${"Error".tr()}: ${snapshot.error}'), + ); return Center(child: Text('Error: ${snapshot.error}')); } else if (snapshot.data == null) { return const SizedBox(); @@ -112,13 +126,23 @@ class MoreStoriesState extends State { VendorModel vendorModel = snapshot.data!; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ClipOval(child: NetworkImageWidget(imageUrl: vendorModel.photo.toString(), width: 50, height: 50, fit: BoxFit.cover)), + ClipOval( + child: NetworkImageWidget( + imageUrl: vendorModel.photo.toString(), + width: 50, + height: 50, + fit: BoxFit.cover, + ), + ), const SizedBox(width: 10), Expanded( child: Column( @@ -129,17 +153,29 @@ class MoreStoriesState extends State { vendorModel.title.toString(), textAlign: TextAlign.center, maxLines: 1, - style: const TextStyle(color: Colors.white, fontSize: 16, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w700), + style: const TextStyle( + color: Colors.white, + fontSize: 16, + overflow: TextOverflow.ellipsis, + fontWeight: FontWeight.w700, + ), ), Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg"), + SvgPicture.asset( + "assets/icons/ic_star.svg", + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount.toString(), reviewSum: vendorModel.reviewsSum.toString())} ${'reviews'.tr()}", textAlign: TextAlign.center, maxLines: 1, - style: const TextStyle(color: AppThemeData.warning300, fontSize: 12, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w700), + style: const TextStyle( + color: AppThemeData.warning300, + fontSize: 12, + overflow: TextOverflow.ellipsis, + fontWeight: FontWeight.w700, + ), ), ], ), @@ -152,8 +188,17 @@ class MoreStoriesState extends State { }, child: Container( padding: const EdgeInsets.all(10.0), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: Colors.grey), - child: SvgPicture.asset("assets/icons/ic_close.svg", colorFilter: ColorFilter.mode(AppThemeData.grey800, BlendMode.srcIn)), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.grey, + ), + child: SvgPicture.asset( + "assets/icons/ic_close.svg", + colorFilter: ColorFilter.mode( + AppThemeData.grey800, + BlendMode.srcIn, + ), + ), ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart b/lib/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart index 06b516e..665f863 100644 --- a/lib/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart +++ b/lib/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import 'category_restaurant_screen.dart'; @@ -22,10 +21,19 @@ class ViewAllCategoryScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Categories".tr(), style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500)), + title: Text( + "Categories".tr(), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), + ), ), body: controller.isLoading.value @@ -34,38 +42,84 @@ class ViewAllCategoryScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: GridView.builder( padding: EdgeInsets.zero, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 3.5 / 6, crossAxisSpacing: 6), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + childAspectRatio: 3.5 / 6, + crossAxisSpacing: 6, + ), itemCount: controller.vendorCategoryModel.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { - VendorCategoryModel vendorCategoryModel = controller.vendorCategoryModel[index]; + VendorCategoryModel vendorCategoryModel = + controller.vendorCategoryModel[index]; return InkWell( onTap: () { - Get.to(const CategoryRestaurantScreen(), arguments: {"vendorCategoryModel": vendorCategoryModel, "dineIn": false}); + Get.to( + const CategoryRestaurantScreen(), + arguments: { + "vendorCategoryModel": vendorCategoryModel, + "dineIn": false, + }, + ); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 4, + vertical: 6, + ), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, strokeAlign: BorderSide.strokeAlignOutside, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100), + side: BorderSide( + width: 1, + strokeAlign: BorderSide.strokeAlignOutside, + color: + isDark + ? AppThemeData.grey800 + : AppThemeData.grey100, + ), borderRadius: BorderRadius.circular(100), ), ), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox(width: 60, height: 60, child: ClipOval(child: NetworkImageWidget(imageUrl: vendorCategoryModel.photo.toString(), fit: BoxFit.cover))), + SizedBox( + width: 60, + height: 60, + child: ClipOval( + child: NetworkImageWidget( + imageUrl: + vendorCategoryModel.photo + .toString(), + fit: BoxFit.cover, + ), + ), + ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: Text( '${vendorCategoryModel.title}', textAlign: TextAlign.center, maxLines: 2, - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 12), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 12, + ), ), ), ], diff --git a/lib/screen_ui/multi_vendor_service/order_list_screen/live_tracking_screen.dart b/lib/screen_ui/multi_vendor_service/order_list_screen/live_tracking_screen.dart index 9bf1d32..7c561fd 100644 --- a/lib/screen_ui/multi_vendor_service/order_list_screen/live_tracking_screen.dart +++ b/lib/screen_ui/multi_vendor_service/order_list_screen/live_tracking_screen.dart @@ -4,7 +4,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart' as flutterMap; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart' as gmap; import '../../../controllers/theme_controller.dart'; @@ -24,17 +24,44 @@ class LiveTrackingScreen extends StatelessWidget { } return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - appBar: AppBar(backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, title: Text("Live Tracking".tr()), centerTitle: false), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + appBar: AppBar( + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + title: Text("Live Tracking".tr()), + centerTitle: false, + ), body: Constant.selectedMapType == 'osm' ? flutterMap.FlutterMap( mapController: controller.osmMapController, - options: flutterMap.MapOptions(initialCenter: controller.driverCurrent.value, initialZoom: 14), + options: flutterMap.MapOptions( + initialCenter: controller.driverCurrent.value, + initialZoom: 14, + ), children: [ - flutterMap.TileLayer(urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'felix.fondex.uz'), - if (controller.routePoints.isNotEmpty) flutterMap.PolylineLayer(polylines: [flutterMap.Polyline(points: controller.routePoints, strokeWidth: 5.0, color: Colors.blue)]), - flutterMap.MarkerLayer(markers: controller.orderModel.value.id == null ? [] : controller.osmMarkers), + flutterMap.TileLayer( + urlTemplate: + 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'felix.fondex.uz', + ), + if (controller.routePoints.isNotEmpty) + flutterMap.PolylineLayer( + polylines: [ + flutterMap.Polyline( + points: controller.routePoints, + strokeWidth: 5.0, + color: Colors.blue, + ), + ], + ), + flutterMap.MarkerLayer( + markers: + controller.orderModel.value.id == null + ? [] + : controller.osmMarkers, + ), ], ) : gmap.GoogleMap( @@ -43,11 +70,18 @@ class LiveTrackingScreen extends StatelessWidget { }, myLocationEnabled: true, zoomControlsEnabled: false, - polylines: Set.of(controller.polyLines.values), + polylines: Set.of( + controller.polyLines.values, + ), markers: Set.of(controller.markers.values), initialCameraPosition: gmap.CameraPosition( zoom: 14, - target: gmap.LatLng(controller.driverUserModel.value.location?.latitude ?? 0.0, controller.driverUserModel.value.location?.longitude ?? 0.0), + target: gmap.LatLng( + controller.driverUserModel.value.location?.latitude ?? + 0.0, + controller.driverUserModel.value.location?.longitude ?? + 0.0, + ), ), ), ); diff --git a/lib/screen_ui/multi_vendor_service/order_list_screen/order_details_screen.dart b/lib/screen_ui/multi_vendor_service/order_list_screen/order_details_screen.dart index ead2ca4..d322880 100644 --- a/lib/screen_ui/multi_vendor_service/order_list_screen/order_details_screen.dart +++ b/lib/screen_ui/multi_vendor_service/order_list_screen/order_details_screen.dart @@ -11,7 +11,7 @@ import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:timelines_plus/timelines_plus.dart'; import '../../../controllers/theme_controller.dart'; @@ -33,12 +33,22 @@ class OrderDetailsScreen extends StatelessWidget { init: OrderDetailsController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Order Details".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Order Details".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: controller.isLoading.value @@ -57,19 +67,38 @@ class OrderDetailsScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "${'Order'.tr()} ${Constant.orderId(orderId: controller.orderModel.value.id.toString())}".tr(), + "${'Order'.tr()} ${Constant.orderId(orderId: controller.orderModel.value.id.toString())}" + .tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 18, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), ), RoundedButtonFill( - title: controller.orderModel.value.status.toString().tr(), - color: Constant.statusColor(status: controller.orderModel.value.status.toString()), + title: + controller.orderModel.value.status + .toString() + .tr(), + color: Constant.statusColor( + status: + controller.orderModel.value.status + .toString(), + ), width: 32, height: 4.5, - textColor: Constant.statusText(status: controller.orderModel.value.status.toString()), + textColor: Constant.statusText( + status: + controller.orderModel.value.status + .toString(), + ), onPress: () async {}, ), ], @@ -77,73 +106,177 @@ class OrderDetailsScreen extends StatelessWidget { const SizedBox(height: 14), controller.orderModel.value.takeAway == true ? Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${controller.orderModel.value.vendor!.title}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), Text( "${controller.orderModel.value.vendor!.location}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + ), ), ], ), ), - controller.orderModel.value.status == Constant.orderPlaced || - controller.orderModel.value.status == Constant.orderRejected || - controller.orderModel.value.status == Constant.orderCompleted + controller.orderModel.value.status == + Constant.orderPlaced || + controller + .orderModel + .value + .status == + Constant.orderRejected || + controller + .orderModel + .value + .status == + Constant.orderCompleted ? const SizedBox() : InkWell( onTap: () { - Constant.makePhoneCall(controller.orderModel.value.vendor!.phonenumber.toString()); + Constant.makePhoneCall( + controller + .orderModel + .value + .vendor! + .phonenumber + .toString(), + ); }, child: Container( width: 42, height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_phone_call.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_phone_call.svg")), ), ), const SizedBox(width: 10), - controller.orderModel.value.status == Constant.orderPlaced || - controller.orderModel.value.status == Constant.orderRejected || - controller.orderModel.value.status == Constant.orderCompleted + controller.orderModel.value.status == + Constant.orderPlaced || + controller + .orderModel + .value + .status == + Constant.orderRejected || + controller + .orderModel + .value + .status == + Constant.orderCompleted ? const SizedBox() : InkWell( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); - UserModel? customer = await FireStoreUtils.getUserProfile(controller.orderModel.value.authorID.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(controller.orderModel.value.vendor!.author.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(restaurantUser!.vendorID.toString()); + UserModel? customer = + await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .authorID + .toString(), + ); + UserModel? restaurantUser = + await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .vendor! + .author + .toString(), + ); + VendorModel? vendorModel = + await FireStoreUtils.getVendorById( + restaurantUser!.vendorID + .toString(), + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": customer!.fullName(), - "restaurantName": vendorModel!.title, - "orderId": controller.orderModel.value.id, - "restaurantId": restaurantUser.id, + "customerName": + customer!.fullName(), + "restaurantName": + vendorModel!.title, + "orderId": + controller + .orderModel + .value + .id, + "restaurantId": + restaurantUser.id, "customerId": customer.id, - "customerProfileImage": customer.profilePictureURL, - "restaurantProfileImage": vendorModel.photo, - "token": restaurantUser.fcmToken, + "customerProfileImage": + customer + .profilePictureURL, + "restaurantProfileImage": + vendorModel.photo, + "token": + restaurantUser.fcmToken, "chatType": "restaurant", }, ); @@ -153,11 +286,29 @@ class OrderDetailsScreen extends StatelessWidget { height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_wechat.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_wechat.svg")), ), ), ], @@ -165,15 +316,26 @@ class OrderDetailsScreen extends StatelessWidget { ), ) : Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( children: [ Timeline.tileBuilder( shrinkWrap: true, padding: EdgeInsets.zero, - physics: const NeverScrollableScrollPhysics(), + physics: + const NeverScrollableScrollPhysics(), theme: TimelineThemeData( nodePosition: 0, // indicatorPosition: 0, @@ -181,81 +343,219 @@ class OrderDetailsScreen extends StatelessWidget { builder: TimelineTileBuilder.connected( contentsAlign: ContentsAlign.basic, indicatorBuilder: (context, index) { - return SvgPicture.asset("assets/icons/ic_location.svg"); + return SvgPicture.asset( + "assets/icons/ic_location.svg", + ); }, - connectorBuilder: (context, index, connectorType) { - return const DashedLineConnector(color: AppThemeData.grey300, gap: 3); + connectorBuilder: ( + context, + index, + connectorType, + ) { + return const DashedLineConnector( + color: AppThemeData.grey300, + gap: 3, + ); }, contentsBuilder: (context, index) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: index == 0 ? Row( children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( "${controller.orderModel.value.vendor!.title}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + fontSize: + 16, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), Text( "${controller.orderModel.value.vendor!.location}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600), + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: + 14, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + ), ), ], ), ), - controller.orderModel.value.status == Constant.orderPlaced || - controller.orderModel.value.status == Constant.orderRejected || - controller.orderModel.value.status == Constant.orderCompleted + controller + .orderModel + .value + .status == + Constant + .orderPlaced || + controller + .orderModel + .value + .status == + Constant + .orderRejected || + controller + .orderModel + .value + .status == + Constant + .orderCompleted ? const SizedBox() : InkWell( onTap: () { - Constant.makePhoneCall(controller.orderModel.value.vendor!.phonenumber.toString()); + Constant.makePhoneCall( + controller + .orderModel + .value + .vendor! + .phonenumber + .toString(), + ); }, child: Container( width: 42, height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: + 1, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_phone_call.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_phone_call.svg")), ), ), - const SizedBox(width: 10), - controller.orderModel.value.status == Constant.orderPlaced || - controller.orderModel.value.status == Constant.orderRejected || - controller.orderModel.value.status == Constant.orderCompleted + const SizedBox( + width: 10, + ), + controller + .orderModel + .value + .status == + Constant + .orderPlaced || + controller + .orderModel + .value + .status == + Constant + .orderRejected || + controller + .orderModel + .value + .status == + Constant + .orderCompleted ? const SizedBox() : InkWell( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait..." + .tr(), + ); - UserModel? customer = await FireStoreUtils.getUserProfile(controller.orderModel.value.authorID.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(controller.orderModel.value.vendor!.author.toString()); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(restaurantUser!.vendorID.toString()); + UserModel? + customer = await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .authorID + .toString(), + ); + UserModel? + restaurantUser = await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .vendor! + .author + .toString(), + ); + VendorModel? + vendorModel = await FireStoreUtils.getVendorById( + restaurantUser! + .vendorID + .toString(), + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": customer!.fullName(), - "restaurantName": vendorModel!.title, - "orderId": controller.orderModel.value.id, - "restaurantId": restaurantUser.id, - "customerId": customer.id, - "customerProfileImage": customer.profilePictureURL, - "restaurantProfileImage": vendorModel.photo, - "token": restaurantUser.fcmToken, - "chatType": "restaurant", + "customerName": + customer! + .fullName(), + "restaurantName": + vendorModel! + .title, + "orderId": + controller + .orderModel + .value + .id, + "restaurantId": + restaurantUser + .id, + "customerId": + customer + .id, + "customerProfileImage": + customer + .profilePictureURL, + "restaurantProfileImage": + vendorModel + .photo, + "token": + restaurantUser + .fcmToken, + "chatType": + "restaurant", }, ); }, @@ -264,27 +564,75 @@ class OrderDetailsScreen extends StatelessWidget { height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: + 1, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_wechat.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_wechat.svg")), ), ), ], ) : Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( "${controller.orderModel.value.address!.addressAs}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), Text( - controller.orderModel.value.address!.getFullAddress(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600), + controller + .orderModel + .value + .address! + .getFullAddress(), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: 14, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + ), ), ], ), @@ -293,93 +641,215 @@ class OrderDetailsScreen extends StatelessWidget { itemCount: 2, ), ), - controller.orderModel.value.status == Constant.orderRejected + controller.orderModel.value.status == + Constant.orderRejected ? const SizedBox() : Column( children: [ - Padding(padding: const EdgeInsets.symmetric(vertical: 10), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), - controller.orderModel.value.status == Constant.orderCompleted && controller.orderModel.value.driver != null + Padding( + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), + child: MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData + .grey200, + ), + ), + controller + .orderModel + .value + .status == + Constant + .orderCompleted && + controller + .orderModel + .value + .driver != + null ? Row( children: [ - SvgPicture.asset("assets/icons/ic_check_small.svg"), + SvgPicture.asset( + "assets/icons/ic_check_small.svg", + ), const SizedBox(width: 5), Text( - controller.orderModel.value.driver!.fullName(), - textAlign: TextAlign.right, + controller + .orderModel + .value + .driver! + .fullName(), + textAlign: + TextAlign.right, style: TextStyle( - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w500, fontSize: 14, ), ), const SizedBox(width: 5), Text( "Order Delivered.".tr(), - textAlign: TextAlign.right, + textAlign: + TextAlign.right, style: TextStyle( - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + fontFamily: + AppThemeData + .regular, + fontWeight: + FontWeight.w500, fontSize: 14, ), ), ], ) - : controller.orderModel.value.status == Constant.orderAccepted || controller.orderModel.value.status == Constant.driverPending + : controller + .orderModel + .value + .status == + Constant + .orderAccepted || + controller + .orderModel + .value + .status == + Constant.driverPending ? Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ - SvgPicture.asset("assets/icons/ic_timer.svg"), + SvgPicture.asset( + "assets/icons/ic_timer.svg", + ), const SizedBox(width: 5), Expanded( child: Text( "${'Your Order has been Preparing and assign to the driver'.tr()}\n${'Preparation Time'.tr()} ${controller.orderModel.value.estimatedTimeToPrepare}" .tr(), - textAlign: TextAlign.start, + textAlign: + TextAlign.start, style: TextStyle( - color: isDark ? AppThemeData.warning400 : AppThemeData.warning400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .warning400 + : AppThemeData + .warning400, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w500, fontSize: 14, ), ), ), ], ) - : controller.orderModel.value.driver != null + : controller + .orderModel + .value + .driver != + null ? Row( children: [ ClipOval( child: NetworkImageWidget( - imageUrl: controller.orderModel.value.author!.profilePictureURL.toString(), + imageUrl: + controller + .orderModel + .value + .author! + .profilePictureURL + .toString(), fit: BoxFit.cover, - height: Responsive.height(5, context), - width: Responsive.width(10, context), + height: + Responsive.height( + 5, + context, + ), + width: + Responsive.width( + 10, + context, + ), ), ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - controller.orderModel.value.driver!.fullName().toString(), - textAlign: TextAlign.start, + controller + .orderModel + .value + .driver! + .fullName() + .toString(), + textAlign: + TextAlign + .start, style: TextStyle( - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, fontSize: 16, ), ), Text( - controller.orderModel.value.driver!.email.toString(), - textAlign: TextAlign.start, + controller + .orderModel + .value + .driver! + .email + .toString(), + textAlign: + TextAlign + .start, style: TextStyle( - color: isDark ? AppThemeData.success400 : AppThemeData.success400, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w400, + color: + isDark + ? AppThemeData + .success400 + : AppThemeData + .success400, + fontFamily: + AppThemeData + .regular, + fontWeight: + FontWeight + .w400, fontSize: 12, ), ), @@ -388,42 +858,104 @@ class OrderDetailsScreen extends StatelessWidget { ), InkWell( onTap: () { - Constant.makePhoneCall(controller.orderModel.value.driver!.phoneNumber.toString()); + Constant.makePhoneCall( + controller + .orderModel + .value + .driver! + .phoneNumber + .toString(), + ); }, child: Container( width: 42, height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_phone_call.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_phone_call.svg")), ), ), const SizedBox(width: 10), InkWell( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait..." + .tr(), + ); - UserModel? customer = await FireStoreUtils.getUserProfile(controller.orderModel.value.authorID.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(controller.orderModel.value.driverID.toString()); + UserModel? customer = + await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .authorID + .toString(), + ); + UserModel? + restaurantUser = + await FireStoreUtils.getUserProfile( + controller + .orderModel + .value + .driverID + .toString(), + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": customer!.fullName(), - "restaurantName": restaurantUser!.fullName(), - "orderId": controller.orderModel.value.id, - "restaurantId": restaurantUser.id, - "customerId": customer.id, - "customerProfileImage": customer.profilePictureURL, - "restaurantProfileImage": restaurantUser.profilePictureURL, - "token": restaurantUser.fcmToken, - "chatType": "Driver", + "customerName": + customer! + .fullName(), + "restaurantName": + restaurantUser! + .fullName(), + "orderId": + controller + .orderModel + .value + .id, + "restaurantId": + restaurantUser + .id, + "customerId": + customer.id, + "customerProfileImage": + customer + .profilePictureURL, + "restaurantProfileImage": + restaurantUser + .profilePictureURL, + "token": + restaurantUser + .fcmToken, + "chatType": + "Driver", }, ); }, @@ -432,11 +964,30 @@ class OrderDetailsScreen extends StatelessWidget { height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_wechat.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_wechat.svg")), ), ), ], @@ -453,44 +1004,100 @@ class OrderDetailsScreen extends StatelessWidget { Text( "Your Order".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: ListView.separated( shrinkWrap: true, padding: EdgeInsets.zero, - itemCount: controller.orderModel.value.products!.length, + itemCount: + controller + .orderModel + .value + .products! + .length, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - CartProductModel cartProductModel = controller.orderModel.value.products![index]; + CartProductModel cartProductModel = + controller + .orderModel + .value + .products![index]; return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(14)), + borderRadius: + const BorderRadius.all( + Radius.circular(14), + ), child: Stack( children: [ NetworkImageWidget( - imageUrl: cartProductModel.photo.toString(), - height: Responsive.height(8, context), - width: Responsive.width(16, context), + imageUrl: + cartProductModel.photo + .toString(), + height: Responsive.height( + 8, + context, + ), + width: Responsive.width( + 16, + context, + ), fit: BoxFit.cover, ), Container( - height: Responsive.height(8, context), - width: Responsive.width(16, context), + height: Responsive.height( + 8, + context, + ), + width: Responsive.width( + 16, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), - end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + begin: const Alignment( + -0.00, + -1.00, + ), + end: const Alignment( + 0, + 1, + ), + colors: [ + Colors.black + .withOpacity(0), + const Color(0xFF111827), + ], ), ), ), @@ -500,69 +1107,173 @@ class OrderDetailsScreen extends StatelessWidget { const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( "${cartProductModel.name}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ), Text( "x ${cartProductModel.quantity}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .regular, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), - double.parse(cartProductModel.discountPrice == null || cartProductModel.discountPrice!.isEmpty ? "0.0" : cartProductModel.discountPrice.toString()) <= 0 + double.parse( + cartProductModel.discountPrice == + null || + cartProductModel + .discountPrice! + .isEmpty + ? "0.0" + : cartProductModel + .discountPrice + .toString(), + ) <= + 0 ? Text( - Constant.amountShow(amount: cartProductModel.price), + Constant.amountShow( + amount: + cartProductModel + .price, + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ) : Row( children: [ Text( - Constant.amountShow(amount: cartProductModel.discountPrice.toString()), + Constant.amountShow( + amount: + cartProductModel + .discountPrice + .toString(), + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), - const SizedBox(width: 5), + const SizedBox( + width: 5, + ), Text( - Constant.amountShow(amount: cartProductModel.price), + Constant.amountShow( + amount: + cartProductModel + .price, + ), style: TextStyle( fontSize: 14, - decoration: TextDecoration.lineThrough, - decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - color: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + decoration: + TextDecoration + .lineThrough, + decorationColor: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + color: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), ], ), Align( - alignment: Alignment.centerRight, + alignment: + Alignment.centerRight, child: RoundedButtonFill( title: "Rate us".tr(), height: 3.8, width: 20, - color: isDark ? AppThemeData.warning300 : AppThemeData.warning300, - textColor: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData + .warning300 + : AppThemeData + .warning300, + textColor: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, onPress: () async { - Get.to(const RateProductScreen(), arguments: {"orderModel": controller.orderModel.value, "productId": cartProductModel.id}); + Get.to( + const RateProductScreen(), + arguments: { + "orderModel": + controller + .orderModel + .value, + "productId": + cartProductModel + .id, + }, + ); }, ), ), @@ -571,63 +1282,149 @@ class OrderDetailsScreen extends StatelessWidget { ), ], ), - cartProductModel.variantInfo == null || cartProductModel.variantInfo!.variantOptions!.isEmpty + cartProductModel.variantInfo == null || + cartProductModel + .variantInfo! + .variantOptions! + .isEmpty ? Container() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 5, + vertical: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Variants".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), const SizedBox(height: 5), Wrap( spacing: 6.0, runSpacing: 6.0, children: - List.generate(cartProductModel.variantInfo!.variantOptions!.length, (i) { - return Container( - decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), - child: Text( - "${cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)} : ${cartProductModel.variantInfo!.variantOptions![cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)]}", - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400), + List.generate( + cartProductModel + .variantInfo! + .variantOptions! + .length, + (i) { + return Container( + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), ), - ), - ); - }).toList(), + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: + 16, + vertical: 5, + ), + child: Text( + "${cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)} : ${cartProductModel.variantInfo!.variantOptions![cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)]}", + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + ), + ), + ), + ); + }, + ).toList(), ), ], ), ), - cartProductModel.extras == null || cartProductModel.extras!.isEmpty + cartProductModel.extras == null || + cartProductModel.extras!.isEmpty ? const SizedBox() : Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( "Addons".tr(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + textAlign: + TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData + .semiBold, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( Constant.amountShow( - amount: (double.parse(cartProductModel.extrasPrice.toString()) * double.parse(cartProductModel.quantity.toString())).toString(), + amount: + (double.parse( + cartProductModel + .extrasPrice + .toString(), + ) * + double.parse( + cartProductModel + .quantity + .toString(), + )) + .toString(), ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontSize: 16, + ), ), ], ), @@ -635,22 +1432,56 @@ class OrderDetailsScreen extends StatelessWidget { spacing: 6.0, runSpacing: 6.0, children: - List.generate(cartProductModel.extras!.length, (i) { - return Container( - decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), - child: Text( - cartProductModel.extras![i].toString(), - textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400), + List.generate( + cartProductModel + .extras! + .length, + (i) { + return Container( + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 8, + ), + ), ), - ), - ); - }).toList(), + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: + 16, + vertical: 5, + ), + child: Text( + cartProductModel + .extras![i] + .toString(), + textAlign: + TextAlign + .start, + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + ), + ), + ), + ); + }, + ).toList(), ), ], ), @@ -658,7 +1489,17 @@ class OrderDetailsScreen extends StatelessWidget { ); }, separatorBuilder: (context, index) { - return Padding(padding: const EdgeInsets.symmetric(vertical: 10), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)); + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 10, + ), + child: MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + ); }, ), ), @@ -692,30 +1533,67 @@ class OrderDetailsScreen extends StatelessWidget { Text( "Bill Details".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Item totals".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.subTotal.value.toString()), + Constant.amountShow( + amount: + controller.subTotal.value + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -723,67 +1601,160 @@ class OrderDetailsScreen extends StatelessWidget { controller.orderModel.value.takeAway == true ? const SizedBox() : Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Delivery Fee".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), - (controller.orderModel.value.vendor?.isSelfDelivery == true) - ? Text('Free Delivery'.tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.regular, color: AppThemeData.success400, fontSize: 16)) + (controller + .orderModel + .value + .vendor + ?.isSelfDelivery == + true) + ? Text( + 'Free Delivery'.tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + AppThemeData.success400, + fontSize: 16, + ), + ) : Text( Constant.amountShow( amount: - controller.orderModel.value.deliveryCharge == null || controller.orderModel.value.deliveryCharge!.isEmpty + controller + .orderModel + .value + .deliveryCharge == + null || + controller + .orderModel + .value + .deliveryCharge! + .isEmpty ? "0.0" - : controller.orderModel.value.deliveryCharge.toString(), + : controller + .orderModel + .value + .deliveryCharge + .toString(), ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData + .grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Coupon Discount".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( "- (${Constant.amountShow(amount: controller.orderModel.value.discount.toString())})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.danger300 + : AppThemeData.danger300, + fontSize: 16, + ), ), ], ), - controller.orderModel.value.specialDiscount != null && controller.orderModel.value.specialDiscount!['special_discount'] != null + controller.orderModel.value.specialDiscount != + null && + controller + .orderModel + .value + .specialDiscount!['special_discount'] != + null ? Column( children: [ const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Special Discount".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( "- (${Constant.amountShow(amount: controller.specialDiscountAmount.value.toString())})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .danger300 + : AppThemeData + .danger300, + fontSize: 16, + ), ), ], ), @@ -791,50 +1762,110 @@ class OrderDetailsScreen extends StatelessWidget { ) : const SizedBox(), const SizedBox(height: 10), - controller.orderModel.value.takeAway == true || controller.orderModel.value.vendor?.isSelfDelivery == true + controller.orderModel.value.takeAway == + true || + controller + .orderModel + .value + .vendor + ?.isSelfDelivery == + true ? const SizedBox() : Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Delivery Tips".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData + .grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ], ), ), Text( - Constant.amountShow(amount: controller.orderModel.value.tipAmount.toString()), + Constant.amountShow( + amount: + controller + .orderModel + .value + .tipAmount + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 10), ListView.builder( - itemCount: controller.orderModel.value.taxSetting!.length, + itemCount: + controller + .orderModel + .value + .taxSetting! + .length, shrinkWrap: true, padding: EdgeInsets.zero, - physics: const NeverScrollableScrollPhysics(), + physics: + const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - TaxModel taxModel = controller.orderModel.value.taxSetting![index]; + TaxModel taxModel = + controller + .orderModel + .value + .taxSetting![index]; return Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 5, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "${taxModel.title.toString()} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData + .grey600, + fontSize: 16, + ), ), ), Text( @@ -842,13 +1873,33 @@ class OrderDetailsScreen extends StatelessWidget { amount: Constant.calculateTax( amount: - (controller.subTotal.value - double.parse(controller.orderModel.value.discount.toString()) - controller.specialDiscountAmount.value) + (controller + .subTotal + .value - + double.parse( + controller + .orderModel + .value + .discount + .toString(), + ) - + controller + .specialDiscountAmount + .value) .toString(), taxModel: taxModel, ).toString(), ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -857,19 +1908,38 @@ class OrderDetailsScreen extends StatelessWidget { ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "To Pay".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - Constant.amountShow(amount: controller.totalAmount.value.toString()), + Constant.amountShow( + amount: + controller.totalAmount.value + .toString(), + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -881,37 +1951,72 @@ class OrderDetailsScreen extends StatelessWidget { Text( "Order Details".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Delivery type".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - controller.orderModel.value.takeAway == true + controller.orderModel.value.takeAway == + true ? "TakeAway".tr() - : controller.orderModel.value.scheduleTime == null + : controller + .orderModel + .value + .scheduleTime == + null ? "Standard".tr() : "Schedule".tr(), textAlign: TextAlign.start, style: TextStyle( fontFamily: AppThemeData.medium, color: - controller.orderModel.value.scheduleTime != null + controller + .orderModel + .value + .scheduleTime != + null ? AppThemeData.primary300 : isDark ? AppThemeData.grey50 @@ -923,60 +2028,121 @@ class OrderDetailsScreen extends StatelessWidget { ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Payment Method".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - controller.orderModel.value.paymentMethod.toString(), + controller + .orderModel + .value + .paymentMethod + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Text( "Date and Time".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( - Constant.timestampToDateTime(controller.orderModel.value.createdAt!), + Constant.timestampToDateTime( + controller + .orderModel + .value + .createdAt!, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ], ), const SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "Phone Number".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: + AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ], ), ), Text( - controller.orderModel.value.author!.phoneNumber.toString(), + controller + .orderModel + .value + .author! + .phoneNumber + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -986,7 +2152,8 @@ class OrderDetailsScreen extends StatelessWidget { ), ), const SizedBox(height: 20), - controller.orderModel.value.notes == null || controller.orderModel.value.notes!.isEmpty + controller.orderModel.value.notes == null || + controller.orderModel.value.notes!.isEmpty ? const SizedBox() : Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -994,18 +2161,44 @@ class OrderDetailsScreen extends StatelessWidget { Text( "Remarks".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 14, + ), child: Text( - controller.orderModel.value.notes.toString(), + controller.orderModel.value.notes + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ), ), @@ -1017,22 +2210,35 @@ class OrderDetailsScreen extends StatelessWidget { ), bottomNavigationBar: controller.orderModel.value.status == Constant.orderShipped || - controller.orderModel.value.status == Constant.orderInTransit || - controller.orderModel.value.status == Constant.orderCompleted + controller.orderModel.value.status == + Constant.orderInTransit || + controller.orderModel.value.status == + Constant.orderCompleted ? Container( color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: Padding( padding: const EdgeInsets.only(bottom: 20), child: - controller.orderModel.value.status == Constant.orderShipped || controller.orderModel.value.status == Constant.orderInTransit + controller.orderModel.value.status == + Constant.orderShipped || + controller.orderModel.value.status == + Constant.orderInTransit ? RoundedButtonFill( title: "Track Order".tr(), height: 5.5, color: AppThemeData.warning300, textColor: AppThemeData.grey900, onPress: () async { - Get.to(const LiveTrackingScreen(), arguments: {"orderModel": controller.orderModel.value}); + Get.to( + const LiveTrackingScreen(), + arguments: { + "orderModel": controller.orderModel.value, + }, + ); }, ) : RoundedButtonFill( @@ -1041,9 +2247,17 @@ class OrderDetailsScreen extends StatelessWidget { color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () async { - for (var element in controller.orderModel.value.products!) { - controller.addToCart(cartProductModel: element); - ShowToastDialog.showToast("Item Added In a cart".tr()); + for (var element + in controller + .orderModel + .value + .products!) { + controller.addToCart( + cartProductModel: element, + ); + ShowToastDialog.showToast( + "Item Added In a cart".tr(), + ); } }, ), diff --git a/lib/screen_ui/multi_vendor_service/order_list_screen/order_screen.dart b/lib/screen_ui/multi_vendor_service/order_list_screen/order_screen.dart index 871c7c4..5853553 100644 --- a/lib/screen_ui/multi_vendor_service/order_list_screen/order_screen.dart +++ b/lib/screen_ui/multi_vendor_service/order_list_screen/order_screen.dart @@ -8,7 +8,7 @@ import 'package:customer/themes/round_button_fill.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; import '../../../widget/my_separator.dart'; @@ -28,7 +28,9 @@ class OrderScreen extends StatelessWidget { builder: (controller) { return Scaffold( body: Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: controller.isLoading.value ? Constant.loader() @@ -41,12 +43,30 @@ class OrderScreen extends StatelessWidget { children: [ Image.asset("assets/images/login.gif", height: 120), const SizedBox(height: 12), - Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "Please Log In to Continue".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -72,15 +92,32 @@ class OrderScreen extends StatelessWidget { children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "My Order".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( - "Keep track your delivered, In Progress and Rejected item all in just one place.".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + "Keep track your delivered, In Progress and Rejected item all in just one place." + .tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ], ), @@ -91,26 +128,51 @@ class OrderScreen extends StatelessWidget { const SizedBox(height: 10), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( children: [ Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 10), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120))), + padding: const EdgeInsets.symmetric( + vertical: 6, + horizontal: 10, + ), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey800 + : AppThemeData.grey100, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 120, + ), + ), + ), child: TabBar( indicator: BoxDecoration( - borderRadius: BorderRadius.circular(50), // Creates border + borderRadius: BorderRadius.circular( + 50, + ), // Creates border color: AppThemeData.primary300, ), labelColor: AppThemeData.grey50, isScrollable: true, tabAlignment: TabAlignment.start, indicatorWeight: 0.5, - unselectedLabelColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + unselectedLabelColor: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, dividerColor: Colors.transparent, indicatorSize: TabBarIndicatorSize.tab, tabs: [ - Padding(padding: const EdgeInsets.symmetric(horizontal: 18), child: Tab(text: 'All'.tr())), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 18, + ), + child: Tab(text: 'All'.tr()), + ), Tab(text: 'In Progress'.tr()), Tab(text: 'Delivered'.tr()), Tab(text: 'Cancelled'.tr()), @@ -123,72 +185,134 @@ class OrderScreen extends StatelessWidget { child: TabBarView( children: [ controller.allList.isEmpty - ? Constant.showEmptyView(message: "Order Not Found".tr()) + ? Constant.showEmptyView( + message: "Order Not Found".tr(), + ) : RefreshIndicator( - onRefresh: () => controller.getOrder(), + onRefresh: + () => controller.getOrder(), child: ListView.builder( - itemCount: controller.allList.length, + itemCount: + controller.allList.length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - OrderModel orderModel = controller.allList[index]; - return itemView(isDark, context, orderModel, controller); + OrderModel orderModel = + controller.allList[index]; + return itemView( + isDark, + context, + orderModel, + controller, + ); }, ), ), controller.inProgressList.isEmpty - ? Constant.showEmptyView(message: "Order Not Found".tr()) + ? Constant.showEmptyView( + message: "Order Not Found".tr(), + ) : RefreshIndicator( - onRefresh: () => controller.getOrder(), + onRefresh: + () => controller.getOrder(), child: ListView.builder( - itemCount: controller.inProgressList.length, + itemCount: + controller + .inProgressList + .length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - OrderModel orderModel = controller.inProgressList[index]; - return itemView(isDark, context, orderModel, controller); + OrderModel orderModel = + controller + .inProgressList[index]; + return itemView( + isDark, + context, + orderModel, + controller, + ); }, ), ), controller.deliveredList.isEmpty - ? Constant.showEmptyView(message: "Order Not Found".tr()) + ? Constant.showEmptyView( + message: "Order Not Found".tr(), + ) : RefreshIndicator( - onRefresh: () => controller.getOrder(), + onRefresh: + () => controller.getOrder(), child: ListView.builder( - itemCount: controller.deliveredList.length, + itemCount: + controller + .deliveredList + .length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - OrderModel orderModel = controller.deliveredList[index]; - return itemView(isDark, context, orderModel, controller); + OrderModel orderModel = + controller + .deliveredList[index]; + return itemView( + isDark, + context, + orderModel, + controller, + ); }, ), ), controller.cancelledList.isEmpty - ? Constant.showEmptyView(message: "Order Not Found".tr()) + ? Constant.showEmptyView( + message: "Order Not Found".tr(), + ) : RefreshIndicator( - onRefresh: () => controller.getOrder(), + onRefresh: + () => controller.getOrder(), child: ListView.builder( - itemCount: controller.cancelledList.length, + itemCount: + controller + .cancelledList + .length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - OrderModel orderModel = controller.cancelledList[index]; - return itemView(isDark, context, orderModel, controller); + OrderModel orderModel = + controller + .cancelledList[index]; + return itemView( + isDark, + context, + orderModel, + controller, + ); }, ), ), controller.rejectedList.isEmpty - ? Constant.showEmptyView(message: "Order Not Found".tr()) + ? Constant.showEmptyView( + message: "Order Not Found".tr(), + ) : RefreshIndicator( - onRefresh: () => controller.getOrder(), + onRefresh: + () => controller.getOrder(), child: ListView.builder( - itemCount: controller.rejectedList.length, + itemCount: + controller + .rejectedList + .length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - OrderModel orderModel = controller.rejectedList[index]; - return itemView(isDark, context, orderModel, controller); + OrderModel orderModel = + controller + .rejectedList[index]; + return itemView( + isDark, + context, + orderModel, + controller, + ); }, ), ), @@ -208,11 +332,21 @@ class OrderScreen extends StatelessWidget { ); } - Padding itemView(isDark, BuildContext context, OrderModel orderModel, OrderController controller) { + Padding itemView( + isDark, + BuildContext context, + OrderModel orderModel, + OrderController controller, + ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -223,12 +357,24 @@ class OrderScreen extends StatelessWidget { borderRadius: const BorderRadius.all(Radius.circular(16)), child: Stack( children: [ - NetworkImageWidget(imageUrl: orderModel.vendor!.photo.toString(), fit: BoxFit.cover, height: Responsive.height(10, context), width: Responsive.width(20, context)), + NetworkImageWidget( + imageUrl: orderModel.vendor!.photo.toString(), + fit: BoxFit.cover, + height: Responsive.height(10, context), + width: Responsive.width(20, context), + ), Container( height: Responsive.height(10, context), width: Responsive.width(20, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, 1.00), end: const Alignment(0, -1), colors: [Colors.black.withOpacity(0), AppThemeData.grey900]), + gradient: LinearGradient( + begin: const Alignment(0.00, 1.00), + end: const Alignment(0, -1), + colors: [ + Colors.black.withOpacity(0), + AppThemeData.grey900, + ], + ), ), ), ], @@ -242,17 +388,39 @@ class OrderScreen extends StatelessWidget { Text( orderModel.status.toString(), textAlign: TextAlign.right, - style: TextStyle(color: Constant.statusColor(status: orderModel.status.toString()), fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500, fontSize: 12), + style: TextStyle( + color: Constant.statusColor( + status: orderModel.status.toString(), + ), + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + fontSize: 12, + ), ), const SizedBox(height: 5), Text( orderModel.vendor!.title.toString(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w400), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 5), Text( Constant.timestampToDateTime(orderModel.createdAt!), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), ), ], ), @@ -272,23 +440,55 @@ class OrderScreen extends StatelessWidget { Expanded( child: Text( "${cartProduct.quantity} x ${cartProduct.name.toString()}", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ), Text( Constant.amountShow( amount: - double.parse(cartProduct.discountPrice.toString()) <= 0 - ? (double.parse('${cartProduct.price ?? 0}') * double.parse('${cartProduct.quantity ?? 0}')).toString() - : (double.parse('${cartProduct.discountPrice ?? 0}') * double.parse('${cartProduct.quantity ?? 0}')).toString(), + double.parse( + cartProduct.discountPrice.toString(), + ) <= + 0 + ? (double.parse('${cartProduct.price ?? 0}') * + double.parse( + '${cartProduct.quantity ?? 0}', + )) + .toString() + : (double.parse( + '${cartProduct.discountPrice ?? 0}', + ) * + double.parse( + '${cartProduct.quantity ?? 0}', + )) + .toString(), + ), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, ), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), ), ], ); }, ), - Padding(padding: const EdgeInsets.symmetric(vertical: 14), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 14), + child: MySeparator( + color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + ), + ), Row( children: [ orderModel.status == Constant.orderCompleted @@ -297,26 +497,48 @@ class OrderScreen extends StatelessWidget { onTap: () { for (var element in orderModel.products!) { controller.addToCart(cartProductModel: element); - ShowToastDialog.showToast("Item Added In a cart".tr()); + ShowToastDialog.showToast( + "Item Added In a cart".tr(), + ); } }, child: Text( "Reorder".tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, fontSize: 16), + style: TextStyle( + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + fontSize: 16, + ), ), ), ) - : orderModel.status == Constant.orderShipped || orderModel.status == Constant.orderInTransit + : orderModel.status == Constant.orderShipped || + orderModel.status == Constant.orderInTransit ? Expanded( child: InkWell( onTap: () { - Get.to(const LiveTrackingScreen(), arguments: {"orderModel": orderModel}); + Get.to( + const LiveTrackingScreen(), + arguments: {"orderModel": orderModel}, + ); }, child: Text( "Track Order".tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, fontSize: 16), + style: TextStyle( + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + fontSize: 16, + ), ), ), ) @@ -324,13 +546,24 @@ class OrderScreen extends StatelessWidget { Expanded( child: InkWell( onTap: () { - Get.to(const OrderDetailsScreen(), arguments: {"orderModel": orderModel}); + Get.to( + const OrderDetailsScreen(), + arguments: {"orderModel": orderModel}, + ); // Get.off(const OrderPlacingScreen(), arguments: {"orderModel": orderModel}); }, child: Text( "View Details".tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, fontSize: 16), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + fontSize: 16, + ), ), ), ), diff --git a/lib/screen_ui/multi_vendor_service/profile_screen/profile_screen.dart b/lib/screen_ui/multi_vendor_service/profile_screen/profile_screen.dart index 81933b3..f725837 100644 --- a/lib/screen_ui/multi_vendor_service/profile_screen/profile_screen.dart +++ b/lib/screen_ui/multi_vendor_service/profile_screen/profile_screen.dart @@ -24,7 +24,7 @@ import 'package:firebase_auth/firebase_auth.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:get/get.dart' hide Trans; import 'package:share_plus/share_plus.dart'; import '../terms_and_condition/terms_and_condition_screen.dart'; @@ -44,7 +44,9 @@ class ProfileScreen extends StatelessWidget { return controller.isLoading.value ? Constant.loader() : Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -53,41 +55,106 @@ class ProfileScreen extends StatelessWidget { children: [ Text( "My Profile".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( - "Manage your personal information, preferences, and settings all in one place.".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + "Manage your personal information, preferences, and settings all in one place." + .tr(), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), const SizedBox(height: 20), Text( "General Information".tr(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), child: Column( children: [ Constant.userModel == null ? const SizedBox() - : cardDecoration(isDark, controller, "assets/images/ic_profile.svg", "Profile Information".tr(), () { - Get.to(const EditProfileScreen()); - }), - if (Constant.sectionConstantModel!.dineInActive == true) - cardDecoration(isDark, controller, "assets/images/ic_dinin.svg", "Dine-In".tr(), () { - Get.to(const DineInScreen()); - }), - cardDecoration(isDark, controller, "assets/images/ic_gift.svg", "Gift Card".tr(), () { - Get.to(const GiftCardScreen()); - }), + : cardDecoration( + isDark, + controller, + "assets/images/ic_profile.svg", + "Profile Information".tr(), + () { + Get.to(const EditProfileScreen()); + }, + ), + if (Constant + .sectionConstantModel! + .dineInActive == + true) + cardDecoration( + isDark, + controller, + "assets/images/ic_dinin.svg", + "Dine-In".tr(), + () { + Get.to(const DineInScreen()); + }, + ), + cardDecoration( + isDark, + controller, + "assets/images/ic_gift.svg", + "Gift Card".tr(), + () { + Get.to(const GiftCardScreen()); + }, + ), if (Constant.isCashbackActive == true) - cardDecoration(isDark, controller, "assets/icons/ic_cashback_Offer.svg", "Cashback Offers".tr(), () { - Get.to(const CashbackOffersListScreen()); - }), + cardDecoration( + isDark, + controller, + "assets/icons/ic_cashback_Offer.svg", + "Cashback Offers".tr(), + () { + Get.to( + const CashbackOffersListScreen(), + ); + }, + ), ], ), ), @@ -99,19 +166,46 @@ class ProfileScreen extends StatelessWidget { children: [ Text( "Bookings Information".tr(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Column( children: [ - cardDecoration(isDark, controller, "assets/icons/ic_dinin_order.svg", "Dine-In Booking".tr(), () { - Get.to(const DineInBookingScreen()); - }), + cardDecoration( + isDark, + controller, + "assets/icons/ic_dinin_order.svg", + "Dine-In Booking".tr(), + () { + Get.to( + const DineInBookingScreen(), + ); + }, + ), ], ), ), @@ -122,20 +216,51 @@ class ProfileScreen extends StatelessWidget { const SizedBox(height: 10), Text( "Preferences".tr(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), child: Column( children: [ - cardDecoration(isDark, controller, "assets/icons/ic_change_language.svg", "Change Language".tr(), () { - Get.to(const ChangeLanguageScreen()); - }), - cardDecoration(isDark, controller, "assets/icons/ic_light_dark.svg", "Dark Mode".tr(), () {}), + cardDecoration( + isDark, + controller, + "assets/icons/ic_change_language.svg", + "Change Language".tr(), + () { + Get.to(const ChangeLanguageScreen()); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_light_dark.svg", + "Dark Mode".tr(), + () {}, + ), ], ), ), @@ -143,31 +268,69 @@ class ProfileScreen extends StatelessWidget { const SizedBox(height: 10), Text( "Social".tr(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), child: Column( children: [ Constant.userModel == null ? const SizedBox() - : cardDecoration(isDark, controller, "assets/icons/ic_refer.svg", "Refer a Friend".tr(), () { - Get.to(const ReferFriendScreen()); - }), - cardDecoration(isDark, controller, "assets/icons/ic_share.svg", "Share app".tr(), () { - Share.share( - '${'Check out Foodie, your ultimate food delivery application!'.tr()} \n\n${'Google Play:'.tr()} ${Constant.googlePlayLink} \n\n${'App Store:'.tr()} ${Constant.appStoreLink}', - subject: 'Look what I made!'.tr(), - ); - }), - cardDecoration(isDark, controller, "assets/icons/ic_rate.svg", "Rate the app".tr(), () { - final InAppReview inAppReview = InAppReview.instance; - inAppReview.requestReview(); - }), + : cardDecoration( + isDark, + controller, + "assets/icons/ic_refer.svg", + "Refer a Friend".tr(), + () { + Get.to(const ReferFriendScreen()); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_share.svg", + "Share app".tr(), + () { + Share.share( + '${'Check out Foodie, your ultimate food delivery application!'.tr()} \n\n${'Google Play:'.tr()} ${Constant.googlePlayLink} \n\n${'App Store:'.tr()} ${Constant.appStoreLink}', + subject: 'Look what I made!'.tr(), + ); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_rate.svg", + "Rate the app".tr(), + () { + final InAppReview inAppReview = + InAppReview.instance; + inAppReview.requestReview(); + }, + ), ], ), ), @@ -180,28 +343,75 @@ class ProfileScreen extends StatelessWidget { children: [ Text( "Communication".tr(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), child: Column( children: [ - cardDecoration(isDark, controller, "assets/icons/ic_restaurant_chat.svg", "Store Inbox".tr(), () { - Get.to(const RestaurantInboxScreen()); - }), - cardDecoration(isDark, controller, "assets/icons/ic_restaurant_driver.svg", "Driver Inbox".tr(), () { - Get.to(const DriverInboxScreen()); - }), - cardDecoration(isDark, controller, "assets/icons/ic_restaurant_chat.svg", "Provider Inbox".tr(), () { - Get.to(const ProviderInboxScreen()); - }), - cardDecoration(isDark, controller, "assets/icons/ic_restaurant_driver.svg", "Worker Inbox".tr(), () { - Get.to(const WorkerInboxScreen()); - }), + cardDecoration( + isDark, + controller, + "assets/icons/ic_restaurant_chat.svg", + "Store Inbox".tr(), + () { + Get.to( + const RestaurantInboxScreen(), + ); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_restaurant_driver.svg", + "Driver Inbox".tr(), + () { + Get.to(const DriverInboxScreen()); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_restaurant_chat.svg", + "Provider Inbox".tr(), + () { + Get.to( + const ProviderInboxScreen(), + ); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_restaurant_driver.svg", + "Worker Inbox".tr(), + () { + Get.to(const WorkerInboxScreen()); + }, + ), ], ), ), @@ -209,21 +419,63 @@ class ProfileScreen extends StatelessWidget { const SizedBox(height: 10), ], ), - Text("Legal".tr(), style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500)), + Text( + "Legal".tr(), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), + ), const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), child: Column( children: [ - cardDecoration(isDark, controller, "assets/icons/ic_privacy_policy.svg", "Privacy Policy".tr(), () { - Get.to(const TermsAndConditionScreen(type: "privacy")); - }), - cardDecoration(isDark, controller, "assets/icons/ic_tearm_condition.svg", "Terms and Conditions".tr(), () { - Get.to(const TermsAndConditionScreen(type: "termAndCondition")); - }), + cardDecoration( + isDark, + controller, + "assets/icons/ic_privacy_policy.svg", + "Privacy Policy".tr(), + () { + Get.to( + const TermsAndConditionScreen( + type: "privacy", + ), + ); + }, + ), + cardDecoration( + isDark, + controller, + "assets/icons/ic_tearm_condition.svg", + "Terms and Conditions".tr(), + () { + Get.to( + const TermsAndConditionScreen( + type: "termAndCondition", + ), + ); + }, + ), ], ), ), @@ -232,39 +484,74 @@ class ProfileScreen extends StatelessWidget { const SizedBox(height: 10), Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), child: Column( children: [ Constant.userModel == null - ? cardDecoration(isDark, controller, "assets/icons/ic_logout.svg", "Log In".tr(), () { - Get.offAll(const LoginScreen()); - }) - : cardDecoration(isDark, controller, "assets/icons/ic_logout.svg", "Log out".tr(), () { - showDialog( - context: context, - builder: (BuildContext context) { - return CustomDialogBox( - title: "Log out".tr(), - descriptions: "Are you sure you want to log out? You will need to enter your credentials to log back in.".tr(), - positiveString: "Log out".tr(), - negativeString: "Cancel".tr(), - positiveClick: () async { - Constant.userModel!.fcmToken = ""; - await FireStoreUtils.updateUser(Constant.userModel!); - Constant.userModel = null; - await FirebaseAuth.instance.signOut(); - Get.offAll(const LoginScreen()); - }, - negativeClick: () { - Get.back(); - }, - img: Image.asset('assets/images/ic_logout.gif', height: 50, width: 50), - ); - }, - ); - }), + ? cardDecoration( + isDark, + controller, + "assets/icons/ic_logout.svg", + "Log In".tr(), + () { + Get.offAll(const LoginScreen()); + }, + ) + : cardDecoration( + isDark, + controller, + "assets/icons/ic_logout.svg", + "Log out".tr(), + () { + showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogBox( + title: "Log out".tr(), + descriptions: + "Are you sure you want to log out? You will need to enter your credentials to log back in." + .tr(), + positiveString: "Log out".tr(), + negativeString: "Cancel".tr(), + positiveClick: () async { + Constant.userModel!.fcmToken = + ""; + await FireStoreUtils.updateUser( + Constant.userModel!, + ); + Constant.userModel = null; + await FirebaseAuth.instance + .signOut(); + Get.offAll( + const LoginScreen(), + ); + }, + negativeClick: () { + Get.back(); + }, + img: Image.asset( + 'assets/images/ic_logout.gif', + height: 50, + width: 50, + ), + ); + }, + ); + }, + ), ], ), ), @@ -273,7 +560,9 @@ class ProfileScreen extends StatelessWidget { Constant.userModel == null ? const SizedBox() : Padding( - padding: const EdgeInsets.symmetric(vertical: 20), + padding: const EdgeInsets.symmetric( + vertical: 20, + ), child: InkWell( onTap: () { showDialog( @@ -281,40 +570,66 @@ class ProfileScreen extends StatelessWidget { builder: (BuildContext context) { return CustomDialogBox( title: "Delete Account".tr(), - descriptions: "Are you sure you want to delete your account? This action is irreversible and will permanently remove all your data.".tr(), + descriptions: + "Are you sure you want to delete your account? This action is irreversible and will permanently remove all your data." + .tr(), positiveString: "Delete".tr(), negativeString: "Cancel".tr(), positiveClick: () async { - ShowToastDialog.showLoader("Please wait...".tr()); - await controller.deleteUserFromServer(); - await FireStoreUtils.deleteUser().then((value) { + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); + await controller + .deleteUserFromServer(); + await FireStoreUtils.deleteUser().then(( + value, + ) { ShowToastDialog.closeLoader(); if (value == true) { - ShowToastDialog.showToast("Account deleted successfully".tr()); + ShowToastDialog.showToast( + "Account deleted successfully" + .tr(), + ); Get.offAll(const LoginScreen()); } else { - ShowToastDialog.showToast("Contact Administrator".tr()); + ShowToastDialog.showToast( + "Contact Administrator".tr(), + ); } }); }, negativeClick: () { Get.back(); }, - img: Image.asset('assets/icons/delete_dialog.gif', height: 50, width: 50), + img: Image.asset( + 'assets/icons/delete_dialog.gif', + height: 50, + width: 50, + ), ); }, ); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_delete.svg"), + SvgPicture.asset( + "assets/icons/ic_delete.svg", + ), const SizedBox(width: 10), Text( "Delete Account".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.danger300 + : AppThemeData.danger300, + ), ), ], ), @@ -324,7 +639,14 @@ class ProfileScreen extends StatelessWidget { child: Text( "V : ${Constant.appVersion}", textAlign: TextAlign.center, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), ], @@ -338,7 +660,13 @@ class ProfileScreen extends StatelessWidget { ); } - Padding cardDecoration(bool isDark, MyProfileController controller, String image, String title, Function()? onPress) { + Padding cardDecoration( + bool isDark, + MyProfileController controller, + String image, + String title, + Function()? onPress, + ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: InkWell( @@ -348,7 +676,18 @@ class ProfileScreen extends StatelessWidget { }, child: Row( children: [ - SvgPicture.asset(image, colorFilter: title == "Log In".tr() || title == "Cashbacks".tr() ? const ColorFilter.mode(AppThemeData.success500, BlendMode.srcIn) : null, height: 24, width: 24), + SvgPicture.asset( + image, + colorFilter: + title == "Log In".tr() || title == "Cashbacks".tr() + ? const ColorFilter.mode( + AppThemeData.success500, + BlendMode.srcIn, + ) + : null, + height: 24, + width: 24, + ), const SizedBox(width: 10), Expanded( child: Text( @@ -362,16 +701,28 @@ class ProfileScreen extends StatelessWidget { ? AppThemeData.danger300 : title == "Log In".tr() ? AppThemeData.success500 - : (isDark ? AppThemeData.grey100 : AppThemeData.grey800), + : (isDark + ? AppThemeData.grey100 + : AppThemeData.grey800), ), ), ), title == "Dark Mode".tr() ? Transform.scale( scale: 0.8, - child: Obx(() => CupertinoSwitch(value: controller.isDarkModeSwitch.value, activeTrackColor: AppThemeData.primary300, onChanged: controller.toggleDarkMode)), + child: Obx( + () => CupertinoSwitch( + value: controller.isDarkModeSwitch.value, + activeTrackColor: AppThemeData.primary300, + onChanged: controller.toggleDarkMode, + ), + ), ) - : Icon(Icons.keyboard_arrow_right, color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700), + : Icon( + Icons.keyboard_arrow_right, + color: + isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, + ), ], ), ), diff --git a/lib/screen_ui/multi_vendor_service/rate_us_screen/rate_product_screen.dart b/lib/screen_ui/multi_vendor_service/rate_us_screen/rate_product_screen.dart index 840a7d1..3dfc208 100644 --- a/lib/screen_ui/multi_vendor_service/rate_us_screen/rate_product_screen.dart +++ b/lib/screen_ui/multi_vendor_service/rate_us_screen/rate_product_screen.dart @@ -10,7 +10,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:image_picker/image_picker.dart'; import '../../../controllers/theme_controller.dart'; @@ -27,33 +27,75 @@ class RateProductScreen extends StatelessWidget { init: RateProductController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Rate the item".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Rate the item".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: SingleChildScrollView( child: Column( children: [ Container( width: Responsive.width(100, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 20, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Rate for".tr(), style: TextStyle(color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.medium)), Text( - "${controller.productModel.value.name}".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 18, fontFamily: AppThemeData.semiBold), + "Rate for".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.medium, + ), + ), + Text( + "${controller.productModel.value.name}" + .tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 18, + fontFamily: AppThemeData.semiBold, + ), ), const SizedBox(height: 10), RatingBar.builder( @@ -62,42 +104,109 @@ class RateProductScreen extends StatelessWidget { direction: Axis.horizontal, itemCount: 5, itemSize: 26, - unratedColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, - itemPadding: const EdgeInsets.symmetric(horizontal: 6.0), - itemBuilder: (context, _) => const Icon(Icons.star, color: AppThemeData.warning300), + unratedColor: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + itemPadding: const EdgeInsets.symmetric( + horizontal: 6.0, + ), + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: AppThemeData.warning300, + ), onRatingUpdate: (double rate) { controller.ratings.value = rate; }, ), - Padding(padding: const EdgeInsets.symmetric(vertical: 20), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 20, + ), + child: MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + ), ListView.builder( - itemCount: controller.reviewAttributeList.length, + itemCount: + controller.reviewAttributeList.length, shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + physics: + const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (context, index) { return Padding( - padding: const EdgeInsets.symmetric(vertical: 2), + padding: const EdgeInsets.symmetric( + vertical: 2, + ), child: Row( children: [ Expanded( child: Text( - controller.reviewAttributeList[index].title.toString(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.semiBold), + controller + .reviewAttributeList[index] + .title + .toString(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData + .grey900, + fontSize: 16, + fontFamily: + AppThemeData.semiBold, + ), ), ), RatingBar.builder( initialRating: - controller.ratingModel.value.id == null ? 0.0 : controller.ratingModel.value.reviewAttributes?[controller.reviewAttributeList[index].id] ?? 0.0, + controller + .ratingModel + .value + .id == + null + ? 0.0 + : controller + .ratingModel + .value + .reviewAttributes?[controller + .reviewAttributeList[index] + .id] ?? + 0.0, minRating: 1, direction: Axis.horizontal, itemCount: 5, itemSize: 18, - unratedColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, - itemPadding: const EdgeInsets.symmetric(horizontal: 2.0), - itemBuilder: (context, _) => const Icon(Icons.star, color: AppThemeData.warning300), + unratedColor: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + itemPadding: + const EdgeInsets.symmetric( + horizontal: 2.0, + ), + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: + AppThemeData.warning300, + ), onRatingUpdate: (double rate) { - controller.reviewAttribute.addEntries([MapEntry(controller.reviewAttributeList[index].id.toString(), rate)]); + controller.reviewAttribute + .addEntries([ + MapEntry( + controller + .reviewAttributeList[index] + .id + .toString(), + rate, + ), + ]); }, ), ], @@ -110,34 +219,72 @@ class RateProductScreen extends StatelessWidget { options: RoundedRectDottedBorderOptions( radius: const Radius.circular(12), dashPattern: const [6, 6, 6, 6], - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, ), child: Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, borderRadius: const BorderRadius.all(Radius.circular(12))), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + borderRadius: const BorderRadius.all( + Radius.circular(12), + ), + ), child: SizedBox( height: Responsive.height(20, context), width: Responsive.width(90, context), child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, children: [ - SvgPicture.asset('assets/icons/ic_folder.svg'), + SvgPicture.asset( + 'assets/icons/ic_folder.svg', + ), const SizedBox(height: 10), Text( - "Choose a image and upload here".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium, fontSize: 16), + "Choose a image and upload here" + .tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontFamily: AppThemeData.medium, + fontSize: 16, + ), ), const SizedBox(height: 5), - Text("JPEG, PNG".tr(), style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular)), + Text( + "JPEG, PNG".tr(), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + fontFamily: + AppThemeData.regular, + ), + ), const SizedBox(height: 10), RoundedButtonFill( title: "Brows Image".tr(), color: AppThemeData.primary50, width: 30, height: 5, - textColor: AppThemeData.primary300, + textColor: + AppThemeData.primary300, onPress: () async { - buildBottomSheet(context, controller); + buildBottomSheet( + context, + controller, + ); }, ), ], @@ -154,21 +301,54 @@ class RateProductScreen extends StatelessWidget { children: [ Expanded( child: ListView.builder( - itemCount: controller.images.length, + itemCount: + controller.images.length, shrinkWrap: true, - scrollDirection: Axis.horizontal, + scrollDirection: + Axis.horizontal, // physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), + padding: + const EdgeInsets.symmetric( + horizontal: 5, + ), child: Stack( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: + const BorderRadius.all( + Radius.circular( + 10, + ), + ), child: - (controller.images[index] is XFile) - ? Image.file(File((controller.images[index] as XFile).path), fit: BoxFit.cover, width: 80, height: 80) - : NetworkImageWidget(imageUrl: controller.images[index]?.toString() ?? '', fit: BoxFit.cover, width: 80, height: 80), + (controller.images[index] + is XFile) + ? Image.file( + File( + (controller.images[index] + as XFile) + .path, + ), + fit: + BoxFit + .cover, + width: 80, + height: 80, + ) + : NetworkImageWidget( + imageUrl: + controller + .images[index] + ?.toString() ?? + '', + fit: + BoxFit + .cover, + width: 80, + height: 80, + ), // controller.images[index].runtimeType == XFile // ? Image.file(File(controller.images[index].path), fit: BoxFit.cover, width: 80, height: 80) // : NetworkImageWidget(imageUrl: controller.images[index], fit: BoxFit.cover, width: 80, height: 80), @@ -180,9 +360,19 @@ class RateProductScreen extends StatelessWidget { right: 0, child: InkWell( onTap: () { - controller.images.removeAt(index); + controller.images + .removeAt( + index, + ); }, - child: const Icon(Icons.remove_circle, size: 28, color: AppThemeData.danger300), + child: const Icon( + Icons + .remove_circle, + size: 28, + color: + AppThemeData + .danger300, + ), ), ), ], @@ -199,26 +389,49 @@ class RateProductScreen extends StatelessWidget { options: RoundedRectDottedBorderOptions( radius: const Radius.circular(12), dashPattern: const [6, 6, 6, 6], - color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, ), child: TextFormField( keyboardType: TextInputType.text, - textCapitalization: TextCapitalization.sentences, - controller: controller.commentController.value, + textCapitalization: + TextCapitalization.sentences, + controller: + controller.commentController.value, maxLines: 4, textInputAction: TextInputAction.done, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + ), decoration: InputDecoration( - errorStyle: const TextStyle(color: Colors.red), + errorStyle: const TextStyle( + color: Colors.red, + ), filled: true, - fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + fillColor: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, disabledBorder: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, errorBorder: InputBorder.none, border: InputBorder.none, hintText: "Type comment".tr(), - hintStyle: TextStyle(fontSize: 14, color: isDark ? AppThemeData.grey600 : AppThemeData.grey400, fontFamily: AppThemeData.regular), + hintStyle: TextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.grey600 + : AppThemeData.grey400, + fontFamily: AppThemeData.regular, + ), ), ), ), @@ -251,7 +464,10 @@ class RateProductScreen extends StatelessWidget { ); } - Future buildBottomSheet(BuildContext context, RateProductController controller) { + Future buildBottomSheet( + BuildContext context, + RateProductController controller, + ) { return showModalBottomSheet( context: context, builder: (context) { @@ -266,7 +482,15 @@ class RateProductScreen extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only(top: 15), - child: Text("Please Select".tr(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16)), + child: Text( + "Please Select".tr(), + style: TextStyle( + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.bold, + fontSize: 16, + ), + ), ), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -277,8 +501,17 @@ class RateProductScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - IconButton(onPressed: () => controller.pickFile(source: ImageSource.camera), icon: const Icon(Icons.camera_alt, size: 32)), - Padding(padding: const EdgeInsets.only(top: 3), child: Text("Camera".tr())), + IconButton( + onPressed: + () => controller.pickFile( + source: ImageSource.camera, + ), + icon: const Icon(Icons.camera_alt, size: 32), + ), + Padding( + padding: const EdgeInsets.only(top: 3), + child: Text("Camera".tr()), + ), ], ), ), @@ -288,8 +521,20 @@ class RateProductScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - IconButton(onPressed: () => controller.pickFile(source: ImageSource.gallery), icon: const Icon(Icons.photo_library_sharp, size: 32)), - Padding(padding: const EdgeInsets.only(top: 3), child: Text("Gallery".tr())), + IconButton( + onPressed: + () => controller.pickFile( + source: ImageSource.gallery, + ), + icon: const Icon( + Icons.photo_library_sharp, + size: 32, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 3), + child: Text("Gallery".tr()), + ), ], ), ), diff --git a/lib/screen_ui/multi_vendor_service/refer_friend_screen/refer_friend_screen.dart b/lib/screen_ui/multi_vendor_service/refer_friend_screen/refer_friend_screen.dart index c8a1bbd..799ae8c 100644 --- a/lib/screen_ui/multi_vendor_service/refer_friend_screen/refer_friend_screen.dart +++ b/lib/screen_ui/multi_vendor_service/refer_friend_screen/refer_friend_screen.dart @@ -7,7 +7,7 @@ import 'package:easy_localization/easy_localization.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:get/get.dart' hide Trans; import 'package:share_plus/share_plus.dart'; import '../../../controllers/theme_controller.dart'; @@ -30,9 +30,16 @@ class ReferFriendScreen extends StatelessWidget { : Container( width: Responsive.width(100, context), height: Responsive.height(100, context), - decoration: const BoxDecoration(image: DecorationImage(image: AssetImage("assets/images/refer_friend.png"), fit: BoxFit.fill)), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/refer_friend.png"), + fit: BoxFit.fill, + ), + ), child: Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -42,30 +49,56 @@ class ReferFriendScreen extends StatelessWidget { onTap: () { Get.back(); }, - child: const Icon(Icons.arrow_back, color: AppThemeData.grey50), + child: const Icon( + Icons.arrow_back, + color: AppThemeData.grey50, + ), ), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 60), - Center(child: SvgPicture.asset("assets/images/referal_top.svg")), + Center( + child: SvgPicture.asset( + "assets/images/referal_top.svg", + ), + ), const SizedBox(height: 10), Text( "Refer your friend and earn".tr(), - style: TextStyle(fontSize: 22, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 22, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), const SizedBox(width: 4), Text( "${Constant.amountShow(amount: Constant.sectionConstantModel!.referralAmount)} ${'Each🎉'.tr()}", - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 32), Text( "Invite Friends & Businesses".tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.ecommerce100 : AppThemeData.ecommerceDark100, + color: + isDark + ? AppThemeData.ecommerce100 + : AppThemeData.ecommerceDark100, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500, ), @@ -75,25 +108,60 @@ class ReferFriendScreen extends StatelessWidget { "${'Invite your friends to sign up with Foodie using your code, and you’ll earn'.tr()} ${Constant.amountShow(amount: Constant.sectionConstantModel!.referralAmount)} ${'after their Success the first order! 💸🍔'.tr()}" .tr(), textAlign: TextAlign.center, - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), const SizedBox(height: 40), Container( decoration: ShapeDecoration( - gradient: const LinearGradient(begin: Alignment(0.00, -1.00), end: Alignment(0, 1), colors: [Color(0xFF271366), Color(0xFF4826B2)]), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), - shadows: const [BoxShadow(color: Color(0x14FFFFFF), blurRadius: 120, offset: Offset(0, 0), spreadRadius: 0)], + gradient: const LinearGradient( + begin: Alignment(0.00, -1.00), + end: Alignment(0, 1), + colors: [ + Color(0xFF271366), + Color(0xFF4826B2), + ], + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(120), + ), + shadows: const [ + BoxShadow( + color: Color(0x14FFFFFF), + blurRadius: 120, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 80, vertical: 16), + padding: const EdgeInsets.symmetric( + horizontal: 80, + vertical: 16, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( - controller.referralModel.value.referralCode.toString(), + controller + .referralModel + .value + .referralCode + .toString(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.ecommerce100 : AppThemeData.ecommerceDark100, + color: + isDark + ? AppThemeData.ecommerce100 + : AppThemeData + .ecommerceDark100, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500, ), @@ -101,34 +169,74 @@ class ReferFriendScreen extends StatelessWidget { const SizedBox(width: 10), InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: controller.referralModel.value.referralCode.toString())); - ShowToastDialog.showToast("Copied".tr()); + Clipboard.setData( + ClipboardData( + text: + controller + .referralModel + .value + .referralCode + .toString(), + ), + ); + ShowToastDialog.showToast( + "Copied".tr(), + ); }, - child: const Icon(Icons.copy, color: AppThemeData.ecommerce100), + child: const Icon( + Icons.copy, + color: AppThemeData.ecommerce100, + ), ), ], ), ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 40), + padding: const EdgeInsets.symmetric( + horizontal: 40, + ), child: Row( children: [ - Expanded(child: Divider(thickness: 1, color: isDark ? AppThemeData.ecommerce100 : AppThemeData.ecommerceDark100)), + Expanded( + child: Divider( + thickness: 1, + color: + isDark + ? AppThemeData.ecommerce100 + : AppThemeData + .ecommerceDark100, + ), + ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30), + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 30, + ), child: Text( "or".tr(), textAlign: TextAlign.center, style: TextStyle( - color: isDark ? AppThemeData.ecommerce100 : AppThemeData.ecommerceDark100, + color: + isDark + ? AppThemeData.ecommerce100 + : AppThemeData + .ecommerceDark100, fontSize: 12, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, ), ), ), - Expanded(child: Divider(color: isDark ? AppThemeData.ecommerce100 : AppThemeData.ecommerceDark100)), + Expanded( + child: Divider( + color: + isDark + ? AppThemeData.ecommerce100 + : AppThemeData + .ecommerceDark100, + ), + ), ], ), ), diff --git a/lib/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart b/lib/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart index 5f6f69e..0112d26 100644 --- a/lib/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart +++ b/lib/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart @@ -17,8 +17,7 @@ import 'package:easy_localization/easy_localization.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:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -52,14 +51,32 @@ class RestaurantDetailsScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('${cartItem.length} ${"items".tr()}', style: TextStyle(fontFamily: AppThemeData.medium, color: AppThemeData.grey50, fontSize: 16)), - Text('View Cart'.tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: AppThemeData.grey50, fontSize: 16, fontWeight: FontWeight.bold)), + Text( + '${cartItem.length} ${"items".tr()}', + style: TextStyle( + fontFamily: AppThemeData.medium, + color: AppThemeData.grey50, + fontSize: 16, + ), + ), + Text( + 'View Cart'.tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: AppThemeData.grey50, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), ], ), ), ), body: NestedScrollView( - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + headerSliverBuilder: ( + BuildContext context, + bool innerBoxIsScrolled, + ) { return [ SliverAppBar( expandedHeight: Responsive.height(30, context), @@ -73,24 +90,48 @@ class RestaurantDetailsScreen extends StatelessWidget { onTap: () { Get.back(); }, - child: Icon(Icons.arrow_back, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + child: Icon( + Icons.arrow_back, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), const Expanded(child: SizedBox()), Visibility( - visible: (controller.vendorModel.value.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (controller.vendorModel.value.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == true), child: Row( children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: BoxDecoration( color: AppThemeData.primary300, - borderRadius: BorderRadius.circular(120), // Optional + borderRadius: BorderRadius.circular( + 120, + ), // Optional ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg"), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + ), const SizedBox(width: 5), - Text("Free Delivery".tr(), style: TextStyle(fontSize: 14, color: AppThemeData.carRent600, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600)), + Text( + "Free Delivery".tr(), + style: TextStyle( + fontSize: 14, + color: AppThemeData.carRent600, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), + ), ], ), ), @@ -100,21 +141,55 @@ class RestaurantDetailsScreen extends StatelessWidget { ), InkWell( onTap: () async { - if (controller.favouriteList.where((p0) => p0.restaurantId == controller.vendorModel.value.id).isNotEmpty) { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: controller.vendorModel.value.id, userId: FireStoreUtils.getCurrentUid()); - controller.favouriteList.removeWhere((item) => item.restaurantId == controller.vendorModel.value.id); - await FireStoreUtils.removeFavouriteRestaurant(favouriteModel); + if (controller.favouriteList + .where( + (p0) => + p0.restaurantId == + controller.vendorModel.value.id, + ) + .isNotEmpty) { + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: controller.vendorModel.value.id, + userId: FireStoreUtils.getCurrentUid(), + ); + controller.favouriteList.removeWhere( + (item) => + item.restaurantId == + controller.vendorModel.value.id, + ); + await FireStoreUtils.removeFavouriteRestaurant( + favouriteModel, + ); } else { - FavouriteModel favouriteModel = FavouriteModel(restaurantId: controller.vendorModel.value.id, userId: FireStoreUtils.getCurrentUid()); + FavouriteModel favouriteModel = FavouriteModel( + restaurantId: controller.vendorModel.value.id, + userId: FireStoreUtils.getCurrentUid(), + ); controller.favouriteList.add(favouriteModel); - await FireStoreUtils.setFavouriteRestaurant(favouriteModel); + await FireStoreUtils.setFavouriteRestaurant( + favouriteModel, + ); } }, child: Obx( () => - controller.favouriteList.where((p0) => p0.restaurantId == controller.vendorModel.value.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg", colorFilter: const ColorFilter.mode(AppThemeData.grey50, BlendMode.srcIn)) - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteList + .where( + (p0) => + p0.restaurantId == + controller.vendorModel.value.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + colorFilter: const ColorFilter.mode( + AppThemeData.grey50, + BlendMode.srcIn, + ), + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), const SizedBox(width: 10), @@ -128,16 +203,30 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, ), ), - badgeStyle: badges.BadgeStyle(shape: badges.BadgeShape.circle, badgeColor: AppThemeData.ecommerce300), + badgeStyle: badges.BadgeStyle( + shape: badges.BadgeShape.circle, + badgeColor: AppThemeData.ecommerce300, + ), child: InkWell( onTap: () { Get.to(const CartScreen()); }, child: ClipOval( - child: SvgPicture.asset("assets/icons/ic_shoping_cart.svg", width: 24, height: 24, colorFilter: const ColorFilter.mode(AppThemeData.grey50, BlendMode.srcIn)), + child: SvgPicture.asset( + "assets/icons/ic_shoping_cart.svg", + width: 24, + height: 24, + colorFilter: const ColorFilter.mode( + AppThemeData.grey50, + BlendMode.srcIn, + ), + ), ), ), ), @@ -147,18 +236,28 @@ class RestaurantDetailsScreen extends StatelessWidget { flexibleSpace: FlexibleSpaceBar( background: Stack( children: [ - controller.vendorModel.value.photos == null || controller.vendorModel.value.photos!.isEmpty + controller.vendorModel.value.photos == null || + controller.vendorModel.value.photos!.isEmpty ? Stack( children: [ NetworkImageWidget( - imageUrl: controller.vendorModel.value.photo.toString(), + imageUrl: + controller.vendorModel.value.photo + .toString(), fit: BoxFit.cover, width: Responsive.width(100, context), height: Responsive.height(40, context), ), Container( decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), Colors.black]), + gradient: LinearGradient( + begin: const Alignment(0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + Colors.black, + ], + ), ), ), ], @@ -167,18 +266,32 @@ class RestaurantDetailsScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), controller: controller.pageController.value, scrollDirection: Axis.horizontal, - itemCount: controller.vendorModel.value.photos!.length, + itemCount: + controller.vendorModel.value.photos!.length, padEnds: false, pageSnapping: true, allowImplicitScrolling: true, itemBuilder: (BuildContext context, int index) { - String image = controller.vendorModel.value.photos![index]; + String image = + controller.vendorModel.value.photos![index]; return Stack( children: [ - NetworkImageWidget(imageUrl: image.toString(), fit: BoxFit.cover, width: Responsive.width(100, context), height: Responsive.height(40, context)), + NetworkImageWidget( + imageUrl: image.toString(), + fit: BoxFit.cover, + width: Responsive.width(100, context), + height: Responsive.height(40, context), + ), Container( decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), Colors.black]), + gradient: LinearGradient( + begin: const Alignment(0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + Colors.black, + ], + ), ), ), ], @@ -192,17 +305,26 @@ class RestaurantDetailsScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, - children: List.generate(controller.vendorModel.value.photos!.length, (index) { - return Obx( - () => Container( - margin: const EdgeInsets.only(right: 5), - alignment: Alignment.centerLeft, - height: 9, - width: 9, - decoration: BoxDecoration(shape: BoxShape.circle, color: controller.currentPage.value == index ? AppThemeData.primary300 : AppThemeData.grey300), - ), - ); - }), + children: List.generate( + controller.vendorModel.value.photos!.length, + (index) { + return Obx( + () => Container( + margin: const EdgeInsets.only(right: 5), + alignment: Alignment.centerLeft, + height: 9, + width: 9, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + controller.currentPage.value == index + ? AppThemeData.primary300 + : AppThemeData.grey300, + ), + ), + ); + }, + ), ), ), ], @@ -223,38 +345,64 @@ class RestaurantDetailsScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.vendorModel.value.title.toString(), + controller.vendorModel.value.title + .toString(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( fontSize: 22, overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), SizedBox( - width: Responsive.width(78, context), + width: Responsive.width( + 78, + context, + ), child: Text( - controller.vendorModel.value.location.toString(), + controller + .vendorModel + .value + .location + .toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, color: isDark ? AppThemeData.grey400 : AppThemeData.grey400), + style: TextStyle( + fontFamily: + AppThemeData.medium, + fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey400, + ), ), ), ], @@ -264,21 +412,60 @@ class RestaurantDetailsScreen extends StatelessWidget { children: [ Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData.primary600 + : AppThemeData.primary50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(120), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + padding: + const EdgeInsets.symmetric( + horizontal: 12, + vertical: 4, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( Constant.calculateReview( - reviewCount: controller.vendorModel.value.reviewsCount.toString(), - reviewSum: controller.vendorModel.value.reviewsSum.toString(), + reviewCount: + controller + .vendorModel + .value + .reviewsCount + .toString(), + reviewSum: + controller + .vendorModel + .value + .reviewsSum + .toString(), + ), + style: TextStyle( + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, ), - style: TextStyle(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), ), ], ), @@ -286,23 +473,45 @@ class RestaurantDetailsScreen extends StatelessWidget { ), InkWell( onTap: () { - Get.to(const ReviewListScreen(), arguments: {"vendorModel": controller.vendorModel.value}); + Get.to( + const ReviewListScreen(), + arguments: { + "vendorModel": + controller + .vendorModel + .value, + }, + ); }, child: Text( "${controller.vendorModel.value.reviewsCount} ${'Ratings'.tr()}", - style: TextStyle(decoration: TextDecoration.underline, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular), + style: TextStyle( + decoration: + TextDecoration.underline, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + fontFamily: + AppThemeData.regular, + ), ), ), ], ), ], ), - Constant.sectionConstantModel!.serviceTypeFlag == "ecommerce-service" + Constant + .sectionConstantModel! + .serviceTypeFlag == + "ecommerce-service" ? SizedBox() : Row( children: [ Text( - controller.isOpen.value ? "Open".tr() : "Close".tr(), + controller.isOpen.value + ? "Open".tr() + : "Close".tr(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( @@ -310,16 +519,41 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: controller.isOpen.value ? AppThemeData.success400 : AppThemeData.danger300, + color: + controller.isOpen.value + ? AppThemeData.success400 + : AppThemeData.danger300, + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Icon( + Icons.circle, + size: 5, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, ), ), - Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child: Icon(Icons.circle, size: 5, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500)), InkWell( onTap: () { - if (controller.vendorModel.value.workingHours!.isEmpty) { - ShowToastDialog.showToast("Timing is not added by store".tr()); + if (controller + .vendorModel + .value + .workingHours! + .isEmpty) { + ShowToastDialog.showToast( + "Timing is not added by store" + .tr(), + ); } else { - timeShowBottomSheet(context, controller); + timeShowBottomSheet( + context, + controller, + ); } }, child: Text( @@ -328,24 +562,45 @@ class RestaurantDetailsScreen extends StatelessWidget { maxLines: 1, style: TextStyle( fontSize: 14, - decoration: TextDecoration.underline, - decorationColor: AppThemeData.ecommerce300, + decoration: + TextDecoration.underline, + decorationColor: + AppThemeData.ecommerce300, overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, ), ), ), ], ), - controller.vendorModel.value.dineInActive == true || (controller.vendorModel.value.openDineTime != null && controller.vendorModel.value.openDineTime!.isNotEmpty) + controller.vendorModel.value.dineInActive == + true || + (controller + .vendorModel + .value + .openDineTime != + null && + controller + .vendorModel + .value + .openDineTime! + .isNotEmpty) ? Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ const SizedBox(height: 20), Text( - "Also applicable on table booking".tr(), + "Also applicable on table booking" + .tr(), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( @@ -353,52 +608,106 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), InkWell( onTap: () { - Get.to(const DineInDetailsScreen(), arguments: {"vendorModel": controller.vendorModel.value}); + Get.to( + const DineInDetailsScreen(), + arguments: { + "vendorModel": + controller + .vendorModel + .value, + }, + ); }, child: Container( height: 80, clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), - borderRadius: BorderRadius.circular(16), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey900 + : AppThemeData + .grey50, + ), + borderRadius: + BorderRadius.circular(16), ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Image.asset("assets/images/ic_table.gif"), + Image.asset( + "assets/images/ic_table.gif", + ), const SizedBox(width: 10), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - "Table Booking".tr(), + "Table Booking" + .tr(), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), Text( - "Quick Conformations".tr(), + "Quick Conformations" + .tr(), style: TextStyle( fontSize: 12, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight + .w500, ), ), ], @@ -415,7 +724,8 @@ class RestaurantDetailsScreen extends StatelessWidget { controller.couponList.isEmpty ? const SizedBox() : Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ const SizedBox(height: 20), Text( @@ -427,11 +737,16 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), - CouponListView(controller: controller), + CouponListView( + controller: controller, + ), ], ), const SizedBox(height: 20), @@ -444,26 +759,42 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), TextFieldWidget( - controller: controller.searchEditingController.value, - hintText: 'Search the item and more...'.tr(), + controller: + controller + .searchEditingController + .value, + hintText: + 'Search the item and more...'.tr(), onchange: (value) { controller.searchProduct(value); }, - prefix: Padding(padding: const EdgeInsets.all(12), child: SvgPicture.asset("assets/icons/ic_search.svg")), + prefix: Padding( + padding: const EdgeInsets.all(12), + child: SvgPicture.asset( + "assets/icons/ic_search.svg", + ), + ), ), const SizedBox(height: 10), - Constant.sectionConstantModel!.isProductDetails == false + Constant + .sectionConstantModel! + .isProductDetails == + false ? SizedBox() : Row( children: [ InkWell( onTap: () { - if (controller.isVag.value == true) { + if (controller.isVag.value == + true) { controller.isVag.value = false; } else { controller.isVag.value = true; @@ -471,30 +802,83 @@ class RestaurantDetailsScreen extends StatelessWidget { controller.filterRecord(); }, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: + const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), decoration: controller.isVag.value ? ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: AppThemeData.primary300), borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .primary600 + : AppThemeData + .primary50, + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + AppThemeData + .primary300, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), ) : ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), ), ), child: Row( mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_veg.svg", height: 20, width: 20), + SvgPicture.asset( + "assets/icons/ic_veg.svg", + height: 20, + width: 20, + ), const SizedBox(width: 8), Text( 'Veg'.tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, + ), ), ], ), @@ -503,38 +887,94 @@ class RestaurantDetailsScreen extends StatelessWidget { const SizedBox(width: 10), InkWell( onTap: () { - if (controller.isNonVag.value == true) { - controller.isNonVag.value = false; + if (controller.isNonVag.value == + true) { + controller.isNonVag.value = + false; } else { - controller.isNonVag.value = true; + controller.isNonVag.value = + true; } controller.filterRecord(); }, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: + const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), decoration: controller.isNonVag.value ? ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: AppThemeData.primary300), borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .primary600 + : AppThemeData + .primary50, + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + AppThemeData + .primary300, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), ) : ShapeDecoration( - color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + color: + isDark + ? AppThemeData + .grey800 + : AppThemeData + .grey100, shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), ), ), child: Row( mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_nonveg.svg", height: 20, width: 20), + SvgPicture.asset( + "assets/icons/ic_nonveg.svg", + height: 20, + width: 20, + ), const SizedBox(width: 8), Text( 'Non Veg'.tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark + ? AppThemeData + .grey100 + : AppThemeData + .grey800, + fontFamily: + AppThemeData.semiBold, + fontWeight: + FontWeight.w600, + ), ), ], ), @@ -631,12 +1071,17 @@ class RestaurantDetailsScreen extends StatelessWidget { ); } - Future timeShowBottomSheet(BuildContext context, RestaurantDetailsController productModel) { + Future timeShowBottomSheet( + BuildContext context, + RestaurantDetailsController productModel, + ) { return showModalBottomSheet( context: context, isScrollControlled: true, isDismissible: true, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), clipBehavior: Clip.antiAliasWithSaveLayer, builder: (context) => FractionallySizedBox( @@ -646,7 +1091,8 @@ class RestaurantDetailsScreen extends StatelessWidget { final themeController = Get.find(); final isDark = themeController.isDark.value; return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -658,7 +1104,15 @@ class RestaurantDetailsScreen extends StatelessWidget { width: 134, height: 5, margin: const EdgeInsets.only(bottom: 6), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey50 : AppThemeData.grey800, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey800, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3), + ), + ), ), ), ), @@ -666,11 +1120,22 @@ class RestaurantDetailsScreen extends StatelessWidget { child: ListView.builder( shrinkWrap: true, physics: const BouncingScrollPhysics(), - itemCount: productModel.vendorModel.value.workingHours!.length, + itemCount: + productModel + .vendorModel + .value + .workingHours! + .length, itemBuilder: (context, dayIndex) { - WorkingHours workingHours = productModel.vendorModel.value.workingHours![dayIndex]; + WorkingHours workingHours = + productModel + .vendorModel + .value + .workingHours![dayIndex]; return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -683,34 +1148,72 @@ class RestaurantDetailsScreen extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), const SizedBox(height: 10), - workingHours.timeslot == null || workingHours.timeslot!.isEmpty + workingHours.timeslot == null || + workingHours.timeslot!.isEmpty ? const SizedBox() : ListView.builder( shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: workingHours.timeslot!.length, + physics: + const NeverScrollableScrollPhysics(), + itemCount: + workingHours.timeslot!.length, itemBuilder: (context, timeIndex) { - Timeslot timeSlotModel = workingHours.timeslot![timeIndex]; + Timeslot timeSlotModel = + workingHours + .timeslot![timeIndex]; return Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all( + 8.0, + ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey200), + borderRadius: + const BorderRadius.all( + Radius.circular( + 12, + ), + ), + border: Border.all( + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey200, + ), ), child: Center( child: Text( - timeSlotModel.from.toString(), - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + timeSlotModel.from + .toString(), + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: 14, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + ), ), ), ), @@ -718,15 +1221,42 @@ class RestaurantDetailsScreen extends StatelessWidget { const SizedBox(width: 10), Expanded( child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey200), + borderRadius: + const BorderRadius.all( + Radius.circular( + 12, + ), + ), + border: Border.all( + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey200, + ), ), child: Center( child: Text( - timeSlotModel.to.toString(), - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + timeSlotModel.to + .toString(), + style: TextStyle( + fontFamily: + AppThemeData + .medium, + fontSize: 14, + color: + isDark + ? AppThemeData + .grey400 + : AppThemeData + .grey500, + ), ), ), ), @@ -775,10 +1305,19 @@ class CouponListView extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100), borderRadius: BorderRadius.circular(16)), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: isDark ? AppThemeData.grey800 : AppThemeData.grey100, + ), + borderRadius: BorderRadius.circular(16), + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: SizedBox( width: Responsive.width(80, context), child: Row( @@ -786,11 +1325,28 @@ class CouponListView extends StatelessWidget { children: [ Container( width: 60, - decoration: const BoxDecoration(image: DecorationImage(image: AssetImage("assets/images/offer_gif.gif"), fit: BoxFit.fill)), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/offer_gif.gif"), + fit: BoxFit.fill, + ), + ), child: Center( child: Text( - offerModel.discountType == "Fix Price" ? Constant.amountShow(amount: offerModel.discount) : "${offerModel.discount}%", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, fontSize: 12), + offerModel.discountType == "Fix Price" + ? Constant.amountShow( + amount: offerModel.discount, + ) + : "${offerModel.discount}%", + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + fontSize: 12, + ), ), ), ), @@ -801,11 +1357,21 @@ class CouponListView extends StatelessWidget { children: [ Text( offerModel.description.toString(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: offerModel.code.toString())).then((value) { + Clipboard.setData( + ClipboardData(text: offerModel.code.toString()), + ).then((value) { ShowToastDialog.showToast("Copied".tr()); }); }, @@ -813,15 +1379,36 @@ class CouponListView extends StatelessWidget { children: [ Text( offerModel.code.toString(), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), const SizedBox(width: 5), SvgPicture.asset("assets/icons/ic_copy.svg"), - const SizedBox(height: 10, child: VerticalDivider()), + const SizedBox( + height: 10, + child: VerticalDivider(), + ), const SizedBox(width: 5), Text( - Constant.timestampToDateTime(offerModel.expiresAt!), - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + Constant.timestampToDateTime( + offerModel.expiresAt!, + ), + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), ], ), @@ -858,7 +1445,8 @@ class ProductListView extends StatelessWidget { itemCount: controller.vendorCategoryList.length, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - VendorCategoryModel vendorCategoryModel = controller.vendorCategoryList[index]; + VendorCategoryModel vendorCategoryModel = + controller.vendorCategoryList[index]; return ExpansionTile( childrenPadding: EdgeInsets.zero, tilePadding: EdgeInsets.zero, @@ -866,17 +1454,33 @@ class ProductListView extends StatelessWidget { initiallyExpanded: true, title: Text( "${vendorCategoryModel.title.toString()} (${controller.productList.where((p0) => p0.categoryID == vendorCategoryModel.id).toList().length})", - style: TextStyle(fontSize: 18, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontSize: 18, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), children: [ Obx( () => ListView.builder( - itemCount: controller.productList.where((p0) => p0.categoryID == vendorCategoryModel.id).toList().length, + itemCount: + controller.productList + .where( + (p0) => p0.categoryID == vendorCategoryModel.id, + ) + .toList() + .length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (context, index) { - ProductModel productModel = controller.productList.where((p0) => p0.categoryID == vendorCategoryModel.id).toList()[index]; + ProductModel productModel = + controller.productList + .where( + (p0) => p0.categoryID == vendorCategoryModel.id, + ) + .toList()[index]; String price = "0.0"; String disPrice = "0.0"; @@ -885,24 +1489,61 @@ class ProductListView extends StatelessWidget { List selectedIndexArray = []; if (productModel.itemAttribute != null) { if (productModel.itemAttribute!.attributes!.isNotEmpty) { - for (var element in productModel.itemAttribute!.attributes!) { + for (var element + in productModel.itemAttribute!.attributes!) { if (element.attributeOptions!.isNotEmpty) { - selectedVariants.add(productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString()); - selectedIndexVariants.add('${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}'); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedVariants.add( + productModel + .itemAttribute! + .attributes![productModel + .itemAttribute! + .attributes! + .indexOf(element)] + .attributeOptions![0] + .toString(), + ); + selectedIndexVariants.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', + ); + selectedIndexArray.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { + if (productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .isNotEmpty) { price = Constant.productCommissionPrice( controller.vendorModel.value, - productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0', + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', ); disPrice = "0"; } } else { - price = Constant.productCommissionPrice(controller.vendorModel.value, productModel.price.toString()); - disPrice = double.parse(productModel.disPrice.toString()) <= 0 ? "0" : Constant.productCommissionPrice(controller.vendorModel.value, productModel.disPrice.toString()); + price = Constant.productCommissionPrice( + controller.vendorModel.value, + productModel.price.toString(), + ); + disPrice = + double.parse(productModel.disPrice.toString()) <= 0 + ? "0" + : Constant.productCommissionPrice( + controller.vendorModel.value, + productModel.disPrice.toString(), + ); } return Padding( padding: const EdgeInsets.only(bottom: 20), @@ -915,16 +1556,30 @@ class ProductListView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Constant.sectionConstantModel!.isProductDetails == false + Constant + .sectionConstantModel! + .isProductDetails == + false ? SizedBox() : Row( children: [ - productModel.nonveg == true ? SvgPicture.asset("assets/icons/ic_nonveg.svg") : SvgPicture.asset("assets/icons/ic_veg.svg"), + productModel.nonveg == true + ? SvgPicture.asset( + "assets/icons/ic_nonveg.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_veg.svg", + ), const SizedBox(width: 5), Text( - productModel.nonveg == true ? "Non Veg.".tr() : "Pure veg.".tr(), + productModel.nonveg == true + ? "Non Veg.".tr() + : "Pure veg.".tr(), style: TextStyle( - color: productModel.nonveg == true ? AppThemeData.danger300 : AppThemeData.success400, + color: + productModel.nonveg == true + ? AppThemeData.danger300 + : AppThemeData.success400, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, ), @@ -934,27 +1589,58 @@ class ProductListView extends StatelessWidget { const SizedBox(height: 5), Text( productModel.name.toString(), - style: TextStyle(fontSize: 18, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), double.parse(disPrice) <= 0 ? Text( Constant.amountShow(amount: price), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ) : Row( children: [ Text( Constant.amountShow(amount: disPrice), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + style: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + ), ), const SizedBox(width: 5), Text( Constant.amountShow(amount: price), style: TextStyle( fontSize: 14, - decoration: TextDecoration.lineThrough, - decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - color: isDark ? AppThemeData.grey500 : AppThemeData.grey400, + decoration: + TextDecoration.lineThrough, + decorationColor: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey500 + : AppThemeData.grey400, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, ), @@ -963,11 +1649,24 @@ class ProductListView extends StatelessWidget { ), Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: const ColorFilter.mode(AppThemeData.warning300, BlendMode.srcIn)), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: const ColorFilter.mode( + AppThemeData.warning300, + BlendMode.srcIn, + ), + ), const SizedBox(width: 5), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount!.toStringAsFixed(0), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsCount!.toStringAsFixed(0)})", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), ], ), @@ -976,7 +1675,10 @@ class ProductListView extends StatelessWidget { maxLines: 2, style: TextStyle( overflow: TextOverflow.ellipsis, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, ), @@ -987,13 +1689,24 @@ class ProductListView extends StatelessWidget { showDialog( context: context, builder: (BuildContext context) { - return infoDialog(controller, isDark, productModel); + return infoDialog( + controller, + isDark, + productModel, + ); }, ); }, child: Row( children: [ - Icon(Icons.info, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, size: 18), + Icon( + Icons.info, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + size: 18, + ), const SizedBox(width: 8), Text( "Info".tr(), @@ -1001,7 +1714,10 @@ class ProductListView extends StatelessWidget { style: TextStyle( overflow: TextOverflow.ellipsis, fontSize: 16, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, ), @@ -1013,15 +1729,29 @@ class ProductListView extends StatelessWidget { ), ), ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: const BorderRadius.all( + Radius.circular(16), + ), child: Stack( children: [ - NetworkImageWidget(imageUrl: productModel.photo.toString(), fit: BoxFit.cover, height: Responsive.height(16, context), width: Responsive.width(34, context)), + NetworkImageWidget( + imageUrl: productModel.photo.toString(), + fit: BoxFit.cover, + height: Responsive.height(16, context), + width: Responsive.width(34, context), + ), Container( height: Responsive.height(16, context), width: Responsive.width(34, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(-0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), const Color(0xFF111827)]), + gradient: LinearGradient( + begin: const Alignment(-0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], + ), ), ), Positioned( @@ -1029,159 +1759,381 @@ class ProductListView extends StatelessWidget { top: 10, child: InkWell( onTap: () async { - if (controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty) { - FavouriteItemModel favouriteModel = FavouriteItemModel( + if (controller.favouriteItemList + .where( + (p0) => + p0.productId == productModel.id, + ) + .isNotEmpty) { + FavouriteItemModel + favouriteModel = FavouriteItemModel( productId: productModel.id, - storeId: controller.vendorModel.value.id, - userId: FireStoreUtils.getCurrentUid(), + storeId: + controller.vendorModel.value.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList + .removeWhere( + (item) => + item.productId == + productModel.id, + ); + await FireStoreUtils.removeFavouriteItem( + favouriteModel, ); - controller.favouriteItemList.removeWhere((item) => item.productId == productModel.id); - await FireStoreUtils.removeFavouriteItem(favouriteModel); } else { - FavouriteItemModel favouriteModel = FavouriteItemModel( + FavouriteItemModel + favouriteModel = FavouriteItemModel( productId: productModel.id, - storeId: controller.vendorModel.value.id, - userId: FireStoreUtils.getCurrentUid(), + storeId: + controller.vendorModel.value.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList.add( + favouriteModel, ); - controller.favouriteItemList.add(favouriteModel); - await FireStoreUtils.setFavouriteItem(favouriteModel); + await FireStoreUtils.setFavouriteItem( + favouriteModel, + ); } }, child: Obx( () => - controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg"), + controller.favouriteItemList + .where( + (p0) => + p0.productId == + productModel.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + ), ), ), ), - controller.isOpen.value == false || Constant.userModel == null + controller.isOpen.value == false || + Constant.userModel == null ? const SizedBox() : Positioned( bottom: 10, left: 20, right: 20, child: - selectedVariants.isNotEmpty || (productModel.addOnsTitle != null && productModel.addOnsTitle!.isNotEmpty) + selectedVariants.isNotEmpty || + (productModel.addOnsTitle != + null && + productModel + .addOnsTitle! + .isNotEmpty) ? RoundedButtonFill( title: "Add".tr(), width: 10, height: 4, - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - textColor: AppThemeData.primary300, + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + textColor: + AppThemeData.primary300, onPress: () async { - controller.selectedVariants.clear(); - controller.selectedIndexVariants.clear(); - controller.selectedIndexArray.clear(); - controller.selectedAddOns.clear(); + controller.selectedVariants + .clear(); + controller + .selectedIndexVariants + .clear(); + controller.selectedIndexArray + .clear(); + controller.selectedAddOns + .clear(); controller.quantity.value = 1; - if (productModel.itemAttribute != null) { - if (productModel.itemAttribute!.attributes!.isNotEmpty) { - for (var element in productModel.itemAttribute!.attributes!) { - if (element.attributeOptions!.isNotEmpty) { + if (productModel + .itemAttribute != + null) { + if (productModel + .itemAttribute! + .attributes! + .isNotEmpty) { + for (var element + in productModel + .itemAttribute! + .attributes!) { + if (element + .attributeOptions! + .isNotEmpty) { controller.selectedVariants.add( - productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString(), + productModel + .itemAttribute! + .attributes![productModel + .itemAttribute! + .attributes! + .indexOf( + element, + )] + .attributeOptions![0] + .toString(), ); - controller.selectedIndexVariants.add( - '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', - ); - controller.selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + controller + .selectedIndexVariants + .add( + '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', + ); + controller + .selectedIndexArray + .add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - final bool productIsInList = cartItem.any( + final bool + productIsInList = cartItem.any( (product) => product.id == "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", ); if (productIsInList) { - CartProductModel element = cartItem.firstWhere( - (product) => - product.id == - "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", - ); - controller.quantity.value = element.quantity!; - if (element.extras != null) { - for (var element in element.extras!) { - controller.selectedAddOns.add(element); + CartProductModel element = + cartItem.firstWhere( + (product) => + product.id == + "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", + ); + controller + .quantity + .value = + element.quantity!; + if (element.extras != + null) { + for (var element + in element + .extras!) { + controller + .selectedAddOns + .add(element); } } } } else { - if (cartItem.where((product) => product.id == "${productModel.id}").isNotEmpty) { - CartProductModel element = cartItem.firstWhere((product) => product.id == "${productModel.id}"); - controller.quantity.value = element.quantity!; - if (element.extras != null) { - for (var element in element.extras!) { - controller.selectedAddOns.add(element); + if (cartItem + .where( + (product) => + product.id == + "${productModel.id}", + ) + .isNotEmpty) { + CartProductModel element = + cartItem.firstWhere( + (product) => + product.id == + "${productModel.id}", + ); + controller + .quantity + .value = + element.quantity!; + if (element.extras != + null) { + for (var element + in element + .extras!) { + controller + .selectedAddOns + .add(element); } } } } controller.update(); - controller.calculatePrice(productModel); - productDetailsBottomSheet(context, productModel); + controller.calculatePrice( + productModel, + ); + productDetailsBottomSheet( + context, + productModel, + ); }, ) : Obx( () => - cartItem.where((p0) => p0.id == productModel.id).isNotEmpty + cartItem + .where( + (p0) => + p0.id == + productModel + .id, + ) + .isNotEmpty ? Container( - width: Responsive.width(100, context), - height: Responsive.height(4, context), + width: + Responsive.width( + 100, + context, + ), + height: + Responsive.height( + 4, + context, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(200)), + color: + isDark + ? AppThemeData + .grey900 + : AppThemeData + .grey50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 200, + ), + ), ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, children: [ InkWell( onTap: () { controller.addToCart( - productModel: productModel, - price: price, - discountPrice: disPrice, - isIncrement: false, - quantity: cartItem.where((p0) => p0.id == productModel.id).first.quantity! - 1, + productModel: + productModel, + price: + price, + discountPrice: + disPrice, + isIncrement: + false, + quantity: + cartItem + .where( + ( + p0, + ) => + p0.id == + productModel.id, + ) + .first + .quantity! - + 1, ); }, - child: Icon(Icons.remove, color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50), + child: Icon( + Icons.remove, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .greyDark50, + ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 14), + padding: + const EdgeInsets.symmetric( + horizontal: + 14, + ), child: Text( - cartItem.where((p0) => p0.id == productModel.id).first.quantity.toString(), - textAlign: TextAlign.start, + cartItem + .where( + (p0) => + p0.id == + productModel.id, + ) + .first + .quantity + .toString(), + textAlign: + TextAlign + .start, maxLines: 1, style: TextStyle( - fontSize: 16, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + fontSize: + 16, + overflow: + TextOverflow + .ellipsis, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight + .w500, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), InkWell( onTap: () { - if ((cartItem.where((p0) => p0.id == productModel.id).first.quantity ?? 0) < (productModel.quantity ?? 0) || - (productModel.quantity ?? 0) == -1) { + if ((cartItem + .where( + ( + p0, + ) => + p0.id == + productModel.id, + ) + .first + .quantity ?? + 0) < + (productModel.quantity ?? + 0) || + (productModel.quantity ?? + 0) == + -1) { controller.addToCart( - productModel: productModel, - price: price, - discountPrice: disPrice, - isIncrement: true, - quantity: cartItem.where((p0) => p0.id == productModel.id).first.quantity! + 1, + productModel: + productModel, + price: + price, + discountPrice: + disPrice, + isIncrement: + true, + quantity: + cartItem + .where( + ( + p0, + ) => + p0.id == + productModel.id, + ) + .first + .quantity! + + 1, ); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock" + .tr(), + ); } }, - child: Icon(Icons.add, color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50), + child: Icon( + Icons.add, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .greyDark50, + ), ), ], ), @@ -1190,13 +2142,39 @@ class ProductListView extends StatelessWidget { title: "Add".tr(), width: 10, height: 4, - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - textColor: AppThemeData.primary300, + color: + isDark + ? AppThemeData + .grey900 + : AppThemeData + .grey50, + textColor: + AppThemeData + .primary300, onPress: () async { - if (1 <= (productModel.quantity ?? 0) || (productModel.quantity ?? 0) == -1) { - controller.addToCart(productModel: productModel, price: price, discountPrice: disPrice, isIncrement: true, quantity: 1); + if (1 <= + (productModel + .quantity ?? + 0) || + (productModel + .quantity ?? + 0) == + -1) { + controller.addToCart( + productModel: + productModel, + price: price, + discountPrice: + disPrice, + isIncrement: + true, + quantity: 1, + ); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock" + .tr(), + ); } }, ), @@ -1218,12 +2196,17 @@ class ProductListView extends StatelessWidget { ); } - Future productDetailsBottomSheet(BuildContext context, ProductModel productModel) { + Future productDetailsBottomSheet( + BuildContext context, + ProductModel productModel, + ) { return showModalBottomSheet( context: context, isScrollControlled: true, isDismissible: true, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), clipBehavior: Clip.antiAliasWithSaveLayer, builder: (context) => FractionallySizedBox( @@ -1237,7 +2220,11 @@ class ProductListView extends StatelessWidget { ); } - Dialog infoDialog(RestaurantDetailsController controller, isDark, ProductModel productModel) { + Dialog infoDialog( + RestaurantDetailsController controller, + isDark, + ProductModel productModel, + ) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), insetPadding: const EdgeInsets.all(10), @@ -1260,17 +2247,33 @@ class ProductListView extends StatelessWidget { Text( "Product Information's".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, fontWeight: FontWeight.w700, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + fontWeight: FontWeight.w700, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), Text( productModel.description.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), ), - productModel.grams == 0 && Constant.sectionConstantModel!.isProductDetails == false + productModel.grams == 0 && + Constant.sectionConstantModel!.isProductDetails == false ? SizedBox.shrink() : Padding( padding: const EdgeInsets.only(bottom: 10), @@ -1281,18 +2284,33 @@ class ProductListView extends StatelessWidget { child: Text( "Gram".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( productModel.grams.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), ), - productModel.calories == 0 && Constant.sectionConstantModel!.isProductDetails == false + productModel.calories == 0 && + Constant.sectionConstantModel!.isProductDetails == false ? SizedBox.shrink() : Padding( padding: const EdgeInsets.only(bottom: 10), @@ -1303,18 +2321,33 @@ class ProductListView extends StatelessWidget { child: Text( "Calories".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( productModel.calories.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), ), - productModel.proteins == 0 && Constant.sectionConstantModel!.isProductDetails == false + productModel.proteins == 0 && + Constant.sectionConstantModel!.isProductDetails == false ? SizedBox.shrink() : Padding( padding: const EdgeInsets.only(bottom: 10), @@ -1325,18 +2358,33 @@ class ProductListView extends StatelessWidget { child: Text( "Proteins".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( productModel.proteins.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), ), - productModel.fats == 0 && Constant.sectionConstantModel!.isProductDetails == false + productModel.fats == 0 && + Constant.sectionConstantModel!.isProductDetails == false ? SizedBox.shrink() : Padding( padding: const EdgeInsets.only(bottom: 10), @@ -1347,19 +2395,34 @@ class ProductListView extends StatelessWidget { child: Text( "Fats".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), ), Text( productModel.fats.toString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), ), - productModel.productSpecification != null && productModel.productSpecification!.isNotEmpty + productModel.productSpecification != null && + productModel.productSpecification!.isNotEmpty ? Padding( padding: const EdgeInsets.only(top: 10), child: Column( @@ -1368,11 +2431,20 @@ class ProductListView extends StatelessWidget { Text( "Specification".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w700, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w700, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), SizedBox(height: 8), ListView.builder( - itemCount: productModel.productSpecification!.length, + itemCount: + productModel.productSpecification!.length, shrinkWrap: true, padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), @@ -1383,14 +2455,30 @@ class ProductListView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - productModel.productSpecification!.keys.elementAt(index), + productModel.productSpecification!.keys + .elementAt(index), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.regular, + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 16, + ), ), Text( - productModel.productSpecification!.values.elementAt(index), + productModel.productSpecification!.values + .elementAt(index), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -1411,13 +2499,28 @@ class ProductListView extends StatelessWidget { Text( "Brand".tr(), textAlign: TextAlign.start, - style: TextStyle(fontWeight: FontWeight.w700, fontFamily: AppThemeData.bold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontWeight: FontWeight.w700, + fontFamily: AppThemeData.bold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), SizedBox(height: 5), Text( controller.getBrandName(productModel.brandId!), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + ), ), ], ), @@ -1454,7 +2557,8 @@ class ProductDetailsView extends StatelessWidget { init: RestaurantDetailsController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1463,19 +2567,36 @@ class ProductDetailsView extends StatelessWidget { Container( color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: const BorderRadius.all( + Radius.circular(16), + ), child: Stack( children: [ - NetworkImageWidget(imageUrl: productModel.photo.toString(), height: Responsive.height(11, context), width: Responsive.width(22, context), fit: BoxFit.cover), + NetworkImageWidget( + imageUrl: productModel.photo.toString(), + height: Responsive.height(11, context), + width: Responsive.width(22, context), + fit: BoxFit.cover, + ), Container( height: Responsive.height(11, context), width: Responsive.width(22, context), decoration: BoxDecoration( - gradient: LinearGradient(begin: const Alignment(-0.00, -1.00), end: const Alignment(0, 1), colors: [Colors.black.withOpacity(0), const Color(0xFF111827)]), + gradient: LinearGradient( + begin: const Alignment(-0.00, -1.00), + end: const Alignment(0, 1), + colors: [ + Colors.black.withOpacity(0), + const Color(0xFF111827), + ], + ), ), ), ], @@ -1498,36 +2619,76 @@ class ProductDetailsView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, ), ), ), InkWell( onTap: () async { - if (controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty) { - FavouriteItemModel favouriteModel = FavouriteItemModel( + if (controller.favouriteItemList + .where( + (p0) => + p0.productId == productModel.id, + ) + .isNotEmpty) { + FavouriteItemModel + favouriteModel = FavouriteItemModel( productId: productModel.id, - storeId: controller.vendorModel.value.id, - userId: FireStoreUtils.getCurrentUid(), + storeId: + controller.vendorModel.value.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList + .removeWhere( + (item) => + item.productId == + productModel.id, + ); + await FireStoreUtils.removeFavouriteItem( + favouriteModel, ); - controller.favouriteItemList.removeWhere((item) => item.productId == productModel.id); - await FireStoreUtils.removeFavouriteItem(favouriteModel); } else { - FavouriteItemModel favouriteModel = FavouriteItemModel( + FavouriteItemModel + favouriteModel = FavouriteItemModel( productId: productModel.id, - storeId: controller.vendorModel.value.id, - userId: FireStoreUtils.getCurrentUid(), + storeId: + controller.vendorModel.value.id, + userId: + FireStoreUtils.getCurrentUid(), + ); + controller.favouriteItemList.add( + favouriteModel, ); - controller.favouriteItemList.add(favouriteModel); - await FireStoreUtils.setFavouriteItem(favouriteModel); + await FireStoreUtils.setFavouriteItem( + favouriteModel, + ); } }, child: Obx( () => - controller.favouriteItemList.where((p0) => p0.productId == productModel.id).isNotEmpty - ? SvgPicture.asset("assets/icons/ic_like_fill.svg") - : SvgPicture.asset("assets/icons/ic_like.svg", colorFilter: const ColorFilter.mode(AppThemeData.grey500, BlendMode.srcIn)), + controller.favouriteItemList + .where( + (p0) => + p0.productId == + productModel.id, + ) + .isNotEmpty + ? SvgPicture.asset( + "assets/icons/ic_like_fill.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_like.svg", + colorFilter: + const ColorFilter.mode( + AppThemeData.grey500, + BlendMode.srcIn, + ), + ), ), ), ], @@ -1535,7 +2696,15 @@ class ProductDetailsView extends StatelessWidget { Text( productModel.description.toString(), textAlign: TextAlign.start, - style: TextStyle(fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontSize: 12, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), @@ -1545,7 +2714,8 @@ class ProductDetailsView extends StatelessWidget { ), ), const SizedBox(height: 10), - productModel.itemAttribute == null || productModel.itemAttribute!.attributes!.isEmpty + productModel.itemAttribute == null || + productModel.itemAttribute!.attributes!.isEmpty ? const SizedBox() : ListView.builder( itemCount: productModel.itemAttribute!.attributes!.length, @@ -1555,129 +2725,275 @@ class ProductDetailsView extends StatelessWidget { itemBuilder: (context, index) { String title = ""; for (var element in controller.attributesList) { - if (productModel.itemAttribute!.attributes![index].attributeId == element.id) { + if (productModel + .itemAttribute! + .attributes![index] + .attributeId == + element.id) { title = element.title.toString(); } } return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 5, + ), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - productModel.itemAttribute!.attributes![index].attributeOptions!.isNotEmpty + productModel + .itemAttribute! + .attributes![index] + .attributeOptions! + .isNotEmpty ? Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Text( title, style: TextStyle( fontSize: 16, overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, + fontFamily: + AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Text( - "Required • Select any 1 option".tr(), + "Required • Select any 1 option" + .tr(), style: TextStyle( fontSize: 12, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, ), ), ), - const Padding(padding: EdgeInsets.symmetric(vertical: 10), child: Divider()), + const Padding( + padding: EdgeInsets.symmetric( + vertical: 10, + ), + child: Divider(), + ), ], ) : Offstage(), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), child: Wrap( spacing: 6.0, runSpacing: 6.0, children: - List.generate(productModel.itemAttribute!.attributes![index].attributeOptions!.length, (i) { - return InkWell( - onTap: () async { - if (controller.selectedIndexVariants.where((element) => element.contains('$index _')).isEmpty) { - controller.selectedVariants.insert(index, productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()); - controller.selectedIndexVariants.add('$index _${productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()}'); - controller.selectedIndexArray.add('${index}_$i'); - } else { - controller.selectedIndexArray.remove( - '${index}_${productModel.itemAttribute!.attributes![index].attributeOptions?.indexOf(controller.selectedIndexVariants.where((element) => element.contains('$index _')).first.replaceAll('$index _', ''))}', - ); - controller.selectedVariants.removeAt(index); - controller.selectedIndexVariants.remove(controller.selectedIndexVariants.where((element) => element.contains('$index _')).first); - controller.selectedVariants.insert(index, productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()); - controller.selectedIndexVariants.add('$index _${productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()}'); - controller.selectedIndexArray.add('${index}_$i'); - } + List.generate( + productModel + .itemAttribute! + .attributes![index] + .attributeOptions! + .length, + (i) { + return InkWell( + onTap: () async { + if (controller + .selectedIndexVariants + .where( + (element) => + element.contains( + '$index _', + ), + ) + .isEmpty) { + controller.selectedVariants + .insert( + index, + productModel + .itemAttribute! + .attributes![index] + .attributeOptions![i] + .toString(), + ); + controller + .selectedIndexVariants + .add( + '$index _${productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()}', + ); + controller + .selectedIndexArray + .add('${index}_$i'); + } else { + controller + .selectedIndexArray + .remove( + '${index}_${productModel.itemAttribute!.attributes![index].attributeOptions?.indexOf(controller.selectedIndexVariants.where((element) => element.contains('$index _')).first.replaceAll('$index _', ''))}', + ); + controller.selectedVariants + .removeAt(index); + controller + .selectedIndexVariants + .remove( + controller + .selectedIndexVariants + .where( + ( + element, + ) => element + .contains( + '$index _', + ), + ) + .first, + ); + controller.selectedVariants + .insert( + index, + productModel + .itemAttribute! + .attributes![index] + .attributeOptions![i] + .toString(), + ); + controller + .selectedIndexVariants + .add( + '$index _${productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()}', + ); + controller + .selectedIndexArray + .add('${index}_$i'); + } - final bool productIsInList = cartItem.any( - (product) => - product.id == - "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", - ); - if (productIsInList) { - CartProductModel element = cartItem.firstWhere( + final bool + productIsInList = cartItem.any( (product) => product.id == "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", ); - controller.quantity.value = element.quantity!; - } else { - controller.quantity.value = 1; - } + if (productIsInList) { + CartProductModel + element = cartItem.firstWhere( + (product) => + product.id == + "${productModel.id}~${productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).isNotEmpty ? productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantId.toString() : ""}", + ); + controller.quantity.value = + element.quantity!; + } else { + controller.quantity.value = + 1; + } - controller.update(); - controller.calculatePrice(productModel); - }, - child: Chip( - shape: const RoundedRectangleBorder(side: BorderSide(color: Colors.transparent), borderRadius: BorderRadius.all(Radius.circular(20))), - label: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - productModel.itemAttribute!.attributes![index].attributeOptions![i].toString(), - style: TextStyle( - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, - fontWeight: FontWeight.w500, - color: - controller.selectedVariants.contains(productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()) - ? Colors.white - : isDark - ? AppThemeData.greyDark800 - : AppThemeData.grey800, + controller.update(); + controller.calculatePrice( + productModel, + ); + }, + child: Chip( + shape: + const RoundedRectangleBorder( + side: BorderSide( + color: + Colors + .transparent, + ), + borderRadius: + BorderRadius.all( + Radius.circular( + 20, + ), + ), ), - ), - ], + label: Row( + mainAxisSize: + MainAxisSize.min, + children: [ + Text( + productModel + .itemAttribute! + .attributes![index] + .attributeOptions![i] + .toString(), + style: TextStyle( + overflow: + TextOverflow + .ellipsis, + fontFamily: + AppThemeData + .medium, + fontWeight: + FontWeight.w500, + color: + controller.selectedVariants.contains( + productModel + .itemAttribute! + .attributes![index] + .attributeOptions![i] + .toString(), + ) + ? Colors.white + : isDark + ? AppThemeData + .greyDark800 + : AppThemeData + .grey800, + ), + ), + ], + ), + backgroundColor: + controller.selectedVariants.contains( + productModel + .itemAttribute! + .attributes![index] + .attributeOptions![i] + .toString(), + ) + ? AppThemeData + .primary300 + : isDark + ? AppThemeData.grey800 + : AppThemeData + .grey100, + elevation: 6.0, + padding: const EdgeInsets.all( + 8.0, + ), ), - backgroundColor: - controller.selectedVariants.contains(productModel.itemAttribute!.attributes![index].attributeOptions![i].toString()) - ? AppThemeData.primary300 - : isDark - ? AppThemeData.grey800 - : AppThemeData.grey100, - elevation: 6.0, - padding: const EdgeInsets.all(8.0), - ), - ); - }).toList(), + ); + }, + ).toList(), ), ), ], @@ -1687,19 +3003,33 @@ class ProductDetailsView extends StatelessWidget { ); }, ), - productModel.addOnsTitle == null || productModel.addOnsTitle!.isEmpty + productModel.addOnsTitle == null || + productModel.addOnsTitle!.isEmpty ? const SizedBox() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 5, + ), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), + padding: const EdgeInsets.symmetric( + horizontal: 12, + ), child: Text( "Addons".tr(), style: TextStyle( @@ -1707,21 +3037,32 @@ class ProductDetailsView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), - const Padding(padding: EdgeInsets.symmetric(vertical: 10), child: Divider()), + const Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Divider(), + ), ListView.builder( itemCount: productModel.addOnsTitle!.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - String title = productModel.addOnsTitle![index]; - String price = productModel.addOnsPrice![index]; + String title = + productModel.addOnsTitle![index]; + String price = + productModel.addOnsPrice![index]; return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( children: [ Expanded( @@ -1734,12 +3075,21 @@ class ProductDetailsView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), Text( - Constant.amountShow(amount: Constant.productCommissionPrice(controller.vendorModel.value, price)), + Constant.amountShow( + amount: + Constant.productCommissionPrice( + controller.vendorModel.value, + price, + ), + ), textAlign: TextAlign.start, maxLines: 1, style: TextStyle( @@ -1747,7 +3097,10 @@ class ProductDetailsView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), const SizedBox(width: 10), @@ -1756,14 +3109,18 @@ class ProductDetailsView extends StatelessWidget { height: 24.0, width: 24.0, child: Checkbox( - value: controller.selectedAddOns.contains(title), - activeColor: AppThemeData.primary300, + value: controller.selectedAddOns + .contains(title), + activeColor: + AppThemeData.primary300, onChanged: (value) { if (value != null) { if (value == true) { - controller.selectedAddOns.add(title); + controller.selectedAddOns + .add(title); } else { - controller.selectedAddOns.remove(title); + controller.selectedAddOns + .remove(title); } controller.update(); } @@ -1795,7 +3152,15 @@ class ProductDetailsView extends StatelessWidget { child: Container( width: Responsive.width(100, context), height: Responsive.height(5.5, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(200))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(200), + ), + ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -1807,7 +3172,13 @@ class ProductDetailsView extends StatelessWidget { controller.update(); } }, - child: Icon(Icons.remove, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + child: Icon( + Icons.remove, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -1820,32 +3191,58 @@ class ProductDetailsView extends StatelessWidget { overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, ), ), ), InkWell( onTap: () { if (productModel.itemAttribute == null) { - if (controller.quantity.value < (productModel.quantity ?? 0) || (productModel.quantity ?? 0) == -1) { + if (controller.quantity.value < + (productModel.quantity ?? 0) || + (productModel.quantity ?? 0) == -1) { controller.quantity.value += 1; controller.update(); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock".tr(), + ); } } else { int totalQuantity = int.parse( - productModel.itemAttribute!.variants!.where((element) => element.variantSku == controller.selectedVariants.join('-')).first.variantQuantity.toString(), + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == + controller.selectedVariants.join( + '-', + ), + ) + .first + .variantQuantity + .toString(), ); - if (controller.quantity.value < totalQuantity || totalQuantity == -1) { + if (controller.quantity.value < totalQuantity || + totalQuantity == -1) { controller.quantity.value += 1; controller.update(); } else { - ShowToastDialog.showToast("Out of stock".tr()); + ShowToastDialog.showToast( + "Out of stock".tr(), + ); } } }, - child: Icon(Icons.add, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + child: Icon( + Icons.add, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ], ), @@ -1855,7 +3252,9 @@ class ProductDetailsView extends StatelessWidget { Expanded( flex: 2, child: RoundedButtonFill( - title: "${'Add item'.tr()} ${Constant.amountShow(amount: controller.calculatePrice(productModel))}".tr(), + title: + "${'Add item'.tr()} ${Constant.amountShow(amount: controller.calculatePrice(productModel))}" + .tr(), height: 5.5, color: AppThemeData.primary300, textColor: AppThemeData.grey50, @@ -1864,36 +3263,94 @@ class ProductDetailsView extends StatelessWidget { if (productModel.itemAttribute == null) { await controller.addToCart( productModel: productModel, - price: Constant.productCommissionPrice(controller.vendorModel.value, productModel.price.toString()), - discountPrice: double.parse(productModel.disPrice.toString()) <= 0 ? "0" : Constant.productCommissionPrice(controller.vendorModel.value, productModel.disPrice.toString()), + price: Constant.productCommissionPrice( + controller.vendorModel.value, + productModel.price.toString(), + ), + discountPrice: + double.parse( + productModel.disPrice.toString(), + ) <= + 0 + ? "0" + : Constant.productCommissionPrice( + controller.vendorModel.value, + productModel.disPrice.toString(), + ), isIncrement: true, quantity: controller.quantity.value, ); } else { String variantPrice = "0"; - if (productModel.itemAttribute!.variants!.any((e) => e.variantSku == controller.selectedVariants.join('-'))) { + if (productModel.itemAttribute!.variants!.any( + (e) => + e.variantSku == + controller.selectedVariants.join('-'), + )) { variantPrice = Constant.productCommissionPrice( controller.vendorModel.value, - productModel.itemAttribute!.variants!.firstWhere((e) => e.variantSku == controller.selectedVariants.join('-')).variantPrice ?? '0', + productModel.itemAttribute!.variants! + .firstWhere( + (e) => + e.variantSku == + controller.selectedVariants.join( + '-', + ), + ) + .variantPrice ?? + '0', ); } Map mapData = {}; - for (var element in productModel.itemAttribute!.attributes!) { + for (var element + in productModel.itemAttribute!.attributes!) { mapData.addEntries([ MapEntry( - controller.attributesList.firstWhere((e) => e.id == element.attributeId).title.toString(), - controller.selectedVariants[productModel.itemAttribute!.attributes!.indexOf(element)], + controller.attributesList + .firstWhere( + (e) => e.id == element.attributeId, + ) + .title + .toString(), + controller.selectedVariants[productModel + .itemAttribute! + .attributes! + .indexOf(element)], ), ]); } VariantInfo variantInfo = VariantInfo( - variantPrice: productModel.itemAttribute!.variants!.firstWhere((e) => e.variantSku == controller.selectedVariants.join('-')).variantPrice ?? '0', + variantPrice: + productModel.itemAttribute!.variants! + .firstWhere( + (e) => + e.variantSku == + controller.selectedVariants.join('-'), + ) + .variantPrice ?? + '0', variantSku: controller.selectedVariants.join('-'), variantOptions: mapData, - variantImage: productModel.itemAttribute!.variants!.firstWhere((e) => e.variantSku == controller.selectedVariants.join('-')).variantImage ?? '', - variantId: productModel.itemAttribute!.variants!.firstWhere((e) => e.variantSku == controller.selectedVariants.join('-')).variantId ?? '0', + variantImage: + productModel.itemAttribute!.variants! + .firstWhere( + (e) => + e.variantSku == + controller.selectedVariants.join('-'), + ) + .variantImage ?? + '', + variantId: + productModel.itemAttribute!.variants! + .firstWhere( + (e) => + e.variantSku == + controller.selectedVariants.join('-'), + ) + .variantId ?? + '0', ); await controller.addToCart( diff --git a/lib/screen_ui/multi_vendor_service/review_list_screen/review_list_screen.dart b/lib/screen_ui/multi_vendor_service/review_list_screen/review_list_screen.dart index 3cbab3d..27fa696 100644 --- a/lib/screen_ui/multi_vendor_service/review_list_screen/review_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/review_list_screen/review_list_screen.dart @@ -11,8 +11,7 @@ import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import '../../../controllers/theme_controller.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../chat_screens/full_screen_image_viewer.dart'; @@ -27,12 +26,22 @@ class ReviewListScreen extends StatelessWidget { init: ReviewListController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Reviews".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Reviews".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: controller.isLoading.value @@ -40,7 +49,10 @@ class ReviewListScreen extends StatelessWidget { : controller.ratingList.isEmpty ? Constant.showEmptyView(message: "No Review found".tr()) : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: ListView.builder( itemCount: controller.ratingList.length, itemBuilder: (context, index) { @@ -49,21 +61,54 @@ class ReviewListScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 5), child: Container( decoration: ShapeDecoration( - color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), borderRadius: BorderRadius.circular(12)), + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), + borderRadius: BorderRadius.circular(12), + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(ratingModel.uname.toString(), style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.semiBold)), + Text( + ratingModel.uname.toString(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 18, + fontFamily: AppThemeData.semiBold, + ), + ), Visibility( visible: ratingModel.productId != null, child: FutureBuilder( - future: FireStoreUtils.fireStore.collection(CollectionName.vendorProducts).doc(ratingModel.productId?.split('~').first).get(), + future: + FireStoreUtils.fireStore + .collection( + CollectionName.vendorProducts, + ) + .doc( + ratingModel.productId + ?.split('~') + .first, + ) + .get(), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot.connectionState == + ConnectionState.waiting) { return const Text(''); } else { if (snapshot.hasError) { @@ -71,10 +116,21 @@ class ReviewListScreen extends StatelessWidget { } else if (snapshot.data == null) { return const Text(''); } else if (snapshot.data != null) { - ProductModel model = ProductModel.fromJson(snapshot.data!.data()!); + ProductModel model = + ProductModel.fromJson( + snapshot.data!.data()!, + ); return Text( '${'Rate for'.tr()} - ${model.name ?? ''}', - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 14, fontFamily: AppThemeData.semiBold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 14, + fontFamily: + AppThemeData.semiBold, + ), ); } else { return const Text(''); @@ -91,50 +147,101 @@ class ReviewListScreen extends StatelessWidget { direction: Axis.horizontal, itemCount: 5, itemSize: 18, - itemPadding: const EdgeInsets.symmetric(horizontal: 2.0), - itemBuilder: (context, _) => const Icon(Icons.star, color: AppThemeData.warning300), + itemPadding: const EdgeInsets.symmetric( + horizontal: 2.0, + ), + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: AppThemeData.warning300, + ), unratedColor: AppThemeData.grey400, onRatingUpdate: (double rate) {}, ), const SizedBox(height: 5), Visibility( - visible: ratingModel.comment != '' && ratingModel.comment != null, + visible: + ratingModel.comment != '' && + ratingModel.comment != null, child: Text( ratingModel.comment.toString(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontSize: 16, + fontFamily: AppThemeData.medium, + ), ), ), const SizedBox(height: 5), Visibility( - visible: ratingModel.reviewAttributes != null, + visible: + ratingModel.reviewAttributes != null, child: ListView.builder( - itemCount: ratingModel.reviewAttributes!.length, + itemCount: + ratingModel.reviewAttributes!.length, shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + physics: + const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (context, index) { - String key = ratingModel.reviewAttributes!.keys.elementAt(index); - dynamic value = ratingModel.reviewAttributes![key]; + String key = ratingModel + .reviewAttributes! + .keys + .elementAt(index); + dynamic value = + ratingModel.reviewAttributes![key]; return Padding( - padding: const EdgeInsets.symmetric(vertical: 2), + padding: const EdgeInsets.symmetric( + vertical: 2, + ), child: Row( children: [ FutureBuilder( - future: FireStoreUtils.fireStore.collection(CollectionName.reviewAttributes).doc(key).get(), + future: + FireStoreUtils.fireStore + .collection( + CollectionName + .reviewAttributes, + ) + .doc(key) + .get(), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot + .connectionState == + ConnectionState.waiting) { return const Text(''); } else { if (snapshot.hasError) { return const Text(''); - } else if (snapshot.data == null) { + } else if (snapshot.data == + null) { return const Text(''); } else { - ReviewAttributeModel model = ReviewAttributeModel.fromJson(snapshot.data!.data()!); + ReviewAttributeModel + model = + ReviewAttributeModel.fromJson( + snapshot.data! + .data()!, + ); return Expanded( child: Text( - model.title.toString(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.semiBold), + model.title + .toString(), + style: TextStyle( + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontSize: 16, + fontFamily: + AppThemeData + .semiBold, + ), ), ); } @@ -143,15 +250,29 @@ class ReviewListScreen extends StatelessWidget { ), RatingBar.builder( ignoreGestures: true, - initialRating: value == null ? 0.0 : value ?? 0.0, + initialRating: + value == null + ? 0.0 + : value ?? 0.0, minRating: 1, direction: Axis.horizontal, itemCount: 5, itemSize: 15, - unratedColor: AppThemeData.grey400, - itemPadding: const EdgeInsets.symmetric(horizontal: 2.0), - itemBuilder: (context, _) => const Icon(Icons.star, color: AppThemeData.warning300), - onRatingUpdate: (double rate) {}, + unratedColor: + AppThemeData.grey400, + itemPadding: + const EdgeInsets.symmetric( + horizontal: 2.0, + ), + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: + AppThemeData + .warning300, + ), + onRatingUpdate: + (double rate) {}, ), ], ), @@ -169,16 +290,33 @@ class ReviewListScreen extends StatelessWidget { itemBuilder: (context, index) { return InkWell( onTap: () { - Get.to(FullScreenImageViewer(imageUrl: ratingModel.photos?[index])); + Get.to( + FullScreenImageViewer( + imageUrl: + ratingModel + .photos?[index], + ), + ); }, child: Padding( - padding: const EdgeInsets.all(6.0), + padding: const EdgeInsets.all( + 6.0, + ), child: ClipRRect( - borderRadius: BorderRadius.circular(10), + borderRadius: + BorderRadius.circular(10), child: NetworkImageWidget( - imageUrl: ratingModel.photos?[index], - height: Responsive.height(9, context), - width: Responsive.height(8, context), + imageUrl: + ratingModel + .photos?[index], + height: Responsive.height( + 9, + context, + ), + width: Responsive.height( + 8, + context, + ), fit: BoxFit.fill, ), ), @@ -189,8 +327,17 @@ class ReviewListScreen extends StatelessWidget { ), const SizedBox(height: 5), Text( - Constant.timestampToDateTime(ratingModel.createdAt!), - style: TextStyle(color: isDark ? AppThemeData.grey300 : AppThemeData.grey600, fontSize: 14, fontFamily: AppThemeData.medium), + Constant.timestampToDateTime( + ratingModel.createdAt!, + ), + style: TextStyle( + color: + isDark + ? AppThemeData.grey300 + : AppThemeData.grey600, + fontSize: 14, + fontFamily: AppThemeData.medium, + ), ), ], ), diff --git a/lib/screen_ui/multi_vendor_service/scan_qrcode_screen/scan_qr_code_screen.dart b/lib/screen_ui/multi_vendor_service/scan_qrcode_screen/scan_qr_code_screen.dart index 8d13806..2a63623 100644 --- a/lib/screen_ui/multi_vendor_service/scan_qrcode_screen/scan_qr_code_screen.dart +++ b/lib/screen_ui/multi_vendor_service/scan_qrcode_screen/scan_qr_code_screen.dart @@ -3,7 +3,7 @@ import 'package:customer/models/vendor_model.dart'; import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:qr_code_dart_scan/qr_code_dart_scan.dart'; import '../../../controllers/theme_controller.dart'; @@ -24,8 +24,17 @@ class ScanQrCodeScreen extends StatelessWidget { appBar: AppBar( centerTitle: false, titleSpacing: 0, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - title: Text("Scan QR Code".tr(), style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500)), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + title: Text( + "Scan QR Code".tr(), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), + ), ), body: QRCodeDartScanView( // enable scan invert qr code ( default = false) @@ -35,15 +44,21 @@ class ScanQrCodeScreen extends StatelessWidget { Get.back(); ShowToastDialog.showLoader("Please wait...".tr()); if (controller.allNearestRestaurant.isNotEmpty) { - if (controller.allNearestRestaurant.where((vendor) => vendor.id == result.text).isEmpty) { + if (controller.allNearestRestaurant + .where((vendor) => vendor.id == result.text) + .isEmpty) { ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Store is not available".tr()); return; } - VendorModel storeModel = controller.allNearestRestaurant.firstWhere((vendor) => vendor.id == result.text); + VendorModel storeModel = controller.allNearestRestaurant + .firstWhere((vendor) => vendor.id == result.text); ShowToastDialog.closeLoader(); Get.back(); - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": storeModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": storeModel}, + ); } else { Get.back(); ShowToastDialog.showToast("Store is not available".tr()); diff --git a/lib/screen_ui/multi_vendor_service/search_screen/search_screen.dart b/lib/screen_ui/multi_vendor_service/search_screen/search_screen.dart index c7d6acd..0968a8b 100644 --- a/lib/screen_ui/multi_vendor_service/search_screen/search_screen.dart +++ b/lib/screen_ui/multi_vendor_service/search_screen/search_screen.dart @@ -10,8 +10,7 @@ import '../../../controllers/theme_controller.dart'; import 'package:customer/utils/network_image_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../service/fire_store_utils.dart'; import '../../../widget/restaurant_image_view.dart'; import '../restaurant_details_screen/restaurant_details_screen.dart'; @@ -28,21 +27,40 @@ class SearchScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, title: Text( - Constant.sectionConstantModel?.name?.toLowerCase().contains('restaurants') == true ? "Find your favorite products and nearby stores" : "Search Item & Store".tr(), + Constant.sectionConstantModel?.name?.toLowerCase().contains( + 'restaurants', + ) == + true + ? "Find your favorite products and nearby stores" + : "Search Item & Store".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), bottom: PreferredSize( preferredSize: const Size.fromHeight(55), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: TextFieldWidget( - hintText: Constant.sectionConstantModel?.name?.toLowerCase().contains('restaurants') == true ? 'Find your favorite products and nearby stores'.tr() : 'Search the store and item'.tr(), - prefix: Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: SvgPicture.asset("assets/icons/ic_search.svg")), + hintText: + Constant.sectionConstantModel?.name + ?.toLowerCase() + .contains('restaurants') == + true + ? 'Find your favorite products and nearby stores'.tr() + : 'Search the store and item'.tr(), + prefix: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: SvgPicture.asset("assets/icons/ic_search.svg"), + ), controller: null, onchange: (value) { controller.onSearchTextChanged(value); @@ -55,7 +73,10 @@ class SearchScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -68,9 +89,19 @@ class SearchScreen extends StatelessWidget { Text( "Store".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Divider(), ), - const Padding(padding: EdgeInsets.symmetric(vertical: 10), child: Divider()), ], ), ListView.builder( @@ -78,33 +109,74 @@ class SearchScreen extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), itemCount: controller.vendorSearchList.length, itemBuilder: (context, index) { - VendorModel vendorModel = controller.vendorSearchList[index]; + VendorModel vendorModel = + controller.vendorSearchList[index]; return InkWell( onTap: () { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": vendorModel}); + Get.to( + const RestaurantDetailsScreen(), + arguments: {"vendorModel": vendorModel}, + ); }, child: Padding( padding: const EdgeInsets.only(bottom: 20), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Stack( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)), + borderRadius: + const BorderRadius.only( + topLeft: Radius.circular( + 16, + ), + topRight: Radius.circular( + 16, + ), + ), child: Stack( children: [ - RestaurantImageView(vendorModel: vendorModel), + RestaurantImageView( + vendorModel: vendorModel, + ), Container( - height: Responsive.height(20, context), - width: Responsive.width(100, context), + height: Responsive.height( + 20, + context, + ), + width: Responsive.width( + 100, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), - end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + begin: const Alignment( + -0.00, + -1.00, + ), + end: const Alignment( + 0, + 1, + ), + colors: [ + Colors.black + .withOpacity(0), + const Color( + 0xFF111827, + ), + ], ), ), ), @@ -112,53 +184,124 @@ class SearchScreen extends StatelessWidget { ), ), Transform.translate( - offset: Offset(Responsive.width(-3, context), Responsive.height(17.5, context)), + offset: Offset( + Responsive.width(-3, context), + Responsive.height( + 17.5, + context, + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, children: [ Visibility( - visible: (vendorModel.isSelfDelivery == true && Constant.isSelfDeliveryFeature == true), + visible: + (vendorModel.isSelfDelivery == + true && + Constant.isSelfDeliveryFeature == + true), child: Row( children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: BoxDecoration( - color: AppThemeData.success300, - borderRadius: BorderRadius.circular(120), // Optional + color: + AppThemeData + .success300, + borderRadius: + BorderRadius.circular( + 120, + ), // Optional ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_free_delivery.svg"), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_free_delivery.svg", + ), + const SizedBox( + width: 5, + ), Text( - "Free Delivery".tr(), - style: TextStyle(fontSize: 14, color: AppThemeData.success300, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600), + "Free Delivery" + .tr(), + style: TextStyle( + fontSize: 14, + color: + AppThemeData + .success300, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, + ), ), ], ), ), - const SizedBox(width: 6), + const SizedBox( + width: 6, + ), ], ), ), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.primary600 : AppThemeData.primary50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .primary600 + : AppThemeData + .primary50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn)), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .primary300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: 5, + ), Text( "${Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString())} (${vendorModel.reviewsCount!.toStringAsFixed(0)})", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -166,22 +309,54 @@ class SearchScreen extends StatelessWidget { ), const SizedBox(width: 6), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 7, + ), decoration: ShapeDecoration( - color: isDark ? AppThemeData.ecommerce600 : AppThemeData.ecommerce50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + color: + isDark + ? AppThemeData + .ecommerce600 + : AppThemeData + .ecommerce50, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 120, + ), + ), ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_map_distance.svg", colorFilter: ColorFilter.mode(AppThemeData.ecommerce300, BlendMode.srcIn)), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_map_distance.svg", + colorFilter: + ColorFilter.mode( + AppThemeData + .ecommerce300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: 5, + ), Text( "${Constant.getDistance(lat1: vendorModel.latitude.toString(), lng1: vendorModel.longitude.toString(), lat2: Constant.selectedLocation.location!.latitude.toString(), lng2: Constant.selectedLocation.location!.longitude.toString())} ${Constant.distanceType}", style: TextStyle( fontSize: 14, - color: isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .ecommerce300 + : AppThemeData + .ecommerce300, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), ], @@ -194,9 +369,12 @@ class SearchScreen extends StatelessWidget { ), const SizedBox(height: 15), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( vendorModel.title.toString(), @@ -204,9 +382,15 @@ class SearchScreen extends StatelessWidget { maxLines: 1, style: TextStyle( fontSize: 18, - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.semiBold, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.semiBold, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData + .grey900, ), ), Text( @@ -214,10 +398,16 @@ class SearchScreen extends StatelessWidget { textAlign: TextAlign.start, maxLines: 1, style: TextStyle( - overflow: TextOverflow.ellipsis, - fontFamily: AppThemeData.medium, + overflow: + TextOverflow.ellipsis, + fontFamily: + AppThemeData.medium, fontWeight: FontWeight.w500, - color: isDark ? AppThemeData.grey400 : AppThemeData.grey400, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey400, ), ), ], @@ -239,9 +429,19 @@ class SearchScreen extends StatelessWidget { Text( "Items".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Divider(), ), - const Padding(padding: EdgeInsets.symmetric(vertical: 10), child: Divider()), ], ), ListView.builder( @@ -249,15 +449,19 @@ class SearchScreen extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), itemCount: controller.productSearchList.length, itemBuilder: (context, index) { - ProductModel productModel = controller.productSearchList[index]; + ProductModel productModel = + controller.productSearchList[index]; return FutureBuilder( future: getPrice(productModel), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { + if (snapshot.connectionState == + ConnectionState.waiting) { return Constant.loader(); } else { if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); + return Center( + child: Text('Error: ${snapshot.error}'), + ); } else if (snapshot.data == null) { return const SizedBox(); } else { @@ -266,36 +470,79 @@ class SearchScreen extends StatelessWidget { String disPrice = map['disPrice']; return InkWell( onTap: () async { - await FireStoreUtils.getVendorById(productModel.vendorID.toString()).then((value) { + await FireStoreUtils.getVendorById( + productModel.vendorID.toString(), + ).then((value) { if (value != null) { - Get.to(const RestaurantDetailsScreen(), arguments: {"vendorModel": value}); + Get.to( + const RestaurantDetailsScreen(), + arguments: { + "vendorModel": value, + }, + ); } }); }, child: Padding( - padding: const EdgeInsets.only(bottom: 20), + padding: const EdgeInsets.only( + bottom: 20, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Constant.sectionConstantModel!.isProductDetails == false + Constant + .sectionConstantModel! + .isProductDetails == + false ? SizedBox() - : productModel.nonveg == true || productModel.veg == true + : productModel.nonveg == + true || + productModel.veg == + true ? Row( children: [ - productModel.nonveg == true ? SvgPicture.asset("assets/icons/ic_nonveg.svg") : SvgPicture.asset("assets/icons/ic_veg.svg"), - const SizedBox(width: 5), + productModel.nonveg == + true + ? SvgPicture.asset( + "assets/icons/ic_nonveg.svg", + ) + : SvgPicture.asset( + "assets/icons/ic_veg.svg", + ), + const SizedBox( + width: 5, + ), Text( - productModel.nonveg == true ? "Non Veg.".tr() : "Pure veg.".tr(), + productModel.nonveg == + true + ? "Non Veg." + .tr() + : "Pure veg." + .tr(), style: TextStyle( - color: productModel.nonveg == true ? AppThemeData.danger300 : AppThemeData.success400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + productModel.nonveg == + true + ? AppThemeData + .danger300 + : AppThemeData + .success400, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), ], @@ -303,56 +550,129 @@ class SearchScreen extends StatelessWidget { : SizedBox(), const SizedBox(height: 5), Text( - productModel.name.toString(), + productModel.name + .toString(), style: TextStyle( fontSize: 18, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ), double.parse(disPrice) <= 0 ? Text( - Constant.amountShow(amount: price), + Constant.amountShow( + amount: price, + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight.w600, ), ) : Row( children: [ Text( - Constant.amountShow(amount: disPrice), + Constant.amountShow( + amount: + disPrice, + ), style: TextStyle( fontSize: 16, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), - const SizedBox(width: 5), + const SizedBox( + width: 5, + ), Text( - Constant.amountShow(amount: price), + Constant.amountShow( + amount: price, + ), style: TextStyle( fontSize: 14, - decoration: TextDecoration.lineThrough, - decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - color: isDark ? AppThemeData.grey500 : AppThemeData.grey400, - fontFamily: AppThemeData.semiBold, - fontWeight: FontWeight.w600, + decoration: + TextDecoration + .lineThrough, + decorationColor: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + color: + isDark + ? AppThemeData + .grey500 + : AppThemeData + .grey400, + fontFamily: + AppThemeData + .semiBold, + fontWeight: + FontWeight + .w600, ), ), ], ), Row( children: [ - SvgPicture.asset("assets/icons/ic_star.svg", colorFilter: const ColorFilter.mode(AppThemeData.warning300, BlendMode.srcIn)), - const SizedBox(width: 5), + SvgPicture.asset( + "assets/icons/ic_star.svg", + colorFilter: + const ColorFilter.mode( + AppThemeData + .warning300, + BlendMode.srcIn, + ), + ), + const SizedBox( + width: 5, + ), Text( "${Constant.calculateReview(reviewCount: productModel.reviewsCount!.toStringAsFixed(0), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsCount!.toStringAsFixed(0)})", - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .regular, + fontWeight: + FontWeight.w500, + ), ), ], ), @@ -360,33 +680,73 @@ class SearchScreen extends StatelessWidget { "${productModel.description}", maxLines: 2, style: TextStyle( - overflow: TextOverflow.ellipsis, - color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, - fontFamily: AppThemeData.regular, - fontWeight: FontWeight.w400, + overflow: + TextOverflow + .ellipsis, + color: + isDark + ? AppThemeData + .grey50 + : AppThemeData + .grey900, + fontFamily: + AppThemeData + .regular, + fontWeight: + FontWeight.w400, ), ), ], ), ), ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), + borderRadius: + const BorderRadius.all( + Radius.circular(16), + ), child: Stack( children: [ NetworkImageWidget( - imageUrl: productModel.photo.toString(), + imageUrl: + productModel.photo + .toString(), fit: BoxFit.cover, - height: Responsive.height(16, context), - width: Responsive.width(34, context), + height: Responsive.height( + 16, + context, + ), + width: Responsive.width( + 34, + context, + ), ), Container( - height: Responsive.height(16, context), - width: Responsive.width(34, context), + height: Responsive.height( + 16, + context, + ), + width: Responsive.width( + 34, + context, + ), decoration: BoxDecoration( gradient: LinearGradient( - begin: const Alignment(-0.00, -1.00), - end: const Alignment(0, 1), - colors: [Colors.black.withOpacity(0), const Color(0xFF111827)], + begin: + const Alignment( + -0.00, + -1.00, + ), + end: const Alignment( + 0, + 1, + ), + colors: [ + Colors.black + .withOpacity(0), + const Color( + 0xFF111827, + ), + ], ), ), ), @@ -423,24 +783,56 @@ class SearchScreen extends StatelessWidget { print(productModel.price); print(productModel.disPrice); - VendorModel? vendorModel = await FireStoreUtils.getVendorById(productModel.vendorID.toString()); + VendorModel? vendorModel = await FireStoreUtils.getVendorById( + productModel.vendorID.toString(), + ); if (productModel.itemAttribute != null) { if (productModel.itemAttribute!.attributes!.isNotEmpty) { for (var element in productModel.itemAttribute!.attributes!) { if (element.attributeOptions!.isNotEmpty) { - selectedVariants.add(productModel.itemAttribute!.attributes![productModel.itemAttribute!.attributes!.indexOf(element)].attributeOptions![0].toString()); - selectedIndexVariants.add('${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}'); - selectedIndexArray.add('${productModel.itemAttribute!.attributes!.indexOf(element)}_0'); + selectedVariants.add( + productModel + .itemAttribute! + .attributes![productModel.itemAttribute!.attributes!.indexOf( + element, + )] + .attributeOptions![0] + .toString(), + ); + selectedIndexVariants.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}', + ); + selectedIndexArray.add( + '${productModel.itemAttribute!.attributes!.indexOf(element)}_0', + ); } } } - if (productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).isNotEmpty) { - price = Constant.productCommissionPrice(vendorModel!, productModel.itemAttribute!.variants!.where((element) => element.variantSku == selectedVariants.join('-')).first.variantPrice ?? '0'); + if (productModel.itemAttribute!.variants! + .where((element) => element.variantSku == selectedVariants.join('-')) + .isNotEmpty) { + price = Constant.productCommissionPrice( + vendorModel!, + productModel.itemAttribute!.variants! + .where( + (element) => + element.variantSku == selectedVariants.join('-'), + ) + .first + .variantPrice ?? + '0', + ); disPrice = Constant.productCommissionPrice(vendorModel, '0'); } } else { - price = Constant.productCommissionPrice(vendorModel!, productModel.price.toString()); - disPrice = Constant.productCommissionPrice(vendorModel, productModel.disPrice.toString()); + price = Constant.productCommissionPrice( + vendorModel!, + productModel.price.toString(), + ); + disPrice = Constant.productCommissionPrice( + vendorModel, + productModel.disPrice.toString(), + ); } return {'price': price, 'disPrice': disPrice}; diff --git a/lib/screen_ui/multi_vendor_service/terms_and_condition/terms_and_condition_screen.dart b/lib/screen_ui/multi_vendor_service/terms_and_condition/terms_and_condition_screen.dart index a23577b..f1ded87 100644 --- a/lib/screen_ui/multi_vendor_service/terms_and_condition/terms_and_condition_screen.dart +++ b/lib/screen_ui/multi_vendor_service/terms_and_condition/terms_and_condition_screen.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:flutter_html/flutter_html.dart'; import '../../../controllers/theme_controller.dart'; @@ -26,18 +26,39 @@ class TermsAndConditionScreen extends StatelessWidget { onTap: () { Get.back(); }, - child: Icon(Icons.chevron_left_outlined, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + child: Icon( + Icons.chevron_left_outlined, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), title: Text( type == "privacy" ? "Privacy Policy".tr() : "Terms & Conditions".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 18), + style: TextStyle( + color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, + fontFamily: AppThemeData.bold, + fontSize: 18, + ), ), elevation: 0, - bottom: PreferredSize(preferredSize: const Size.fromHeight(4.0), child: Container(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, height: 4.0)), + bottom: PreferredSize( + preferredSize: const Size.fromHeight(4.0), + child: Container( + color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + height: 4.0, + ), + ), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), - child: SingleChildScrollView(child: Html(shrinkWrap: true, data: type == "privacy" ? Constant.privacyPolicy : Constant.termsAndConditions)), + child: SingleChildScrollView( + child: Html( + shrinkWrap: true, + data: + type == "privacy" + ? Constant.privacyPolicy + : Constant.termsAndConditions, + ), + ), ), ); } diff --git a/lib/screen_ui/multi_vendor_service/wallet_screen/payment_list_screen.dart b/lib/screen_ui/multi_vendor_service/wallet_screen/payment_list_screen.dart index a59d6ee..6178b1d 100644 --- a/lib/screen_ui/multi_vendor_service/wallet_screen/payment_list_screen.dart +++ b/lib/screen_ui/multi_vendor_service/wallet_screen/payment_list_screen.dart @@ -9,7 +9,7 @@ import 'package:customer/themes/text_field_widget.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -25,10 +25,19 @@ class PaymentListScreen extends StatelessWidget { builder: (controller) { return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Top up Wallet".tr(), style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500)), + title: Text( + "Top up Wallet".tr(), + style: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + ), + ), ), body: SingleChildScrollView( child: Column( @@ -40,40 +49,152 @@ class PaymentListScreen extends StatelessWidget { title: 'Amount'.tr(), hintText: 'Enter Amount'.tr(), controller: controller.topUpAmountController.value, - textInputType: const TextInputType.numberWithOptions(decimal: true, signed: true), - prefix: Padding(padding: const EdgeInsets.all(12.0), child: Text(Constant.currencyModel!.symbol.toString(), style: const TextStyle(fontSize: 20, color: AppThemeData.grey800))), - inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9]'))], + textInputType: const TextInputType.numberWithOptions( + decimal: true, + signed: true, + ), + prefix: Padding( + padding: const EdgeInsets.all(12.0), + child: Text( + Constant.currencyModel!.symbol.toString(), + style: const TextStyle( + fontSize: 20, + color: AppThemeData.grey800, + ), + ), + ), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9]')), + ], ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Text( "Select Top up Options".tr(), - style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( - decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(20)), color: isDark ? AppThemeData.grey900 : AppThemeData.grey50), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(20)), + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + ), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), + ), + Visibility( + visible: + controller.payStackModel.value.isEnable == true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), - Visibility(visible: controller.orangeMoneyModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png")), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -96,40 +217,101 @@ class PaymentListScreen extends StatelessWidget { if (controller.topUpAmountController.value.text.isEmpty) { ShowToastDialog.showToast("Please Enter Amount".tr()); } else { - if (double.parse(controller.topUpAmountController.value.text) >= double.parse(Constant.minimumAmountToDeposit.toString())) { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.topUpAmountController.value.text, context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.topUpAmountController.value.text); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.topUpAmountController.value.text), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.topUpAmountController.value.text, orderId: result.id); - } - }); + if (double.parse( + controller.topUpAmountController.value.text, + ) >= + double.parse( + Constant.minimumAmountToDeposit.toString(), + )) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.topUpAmountController.value.text, + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.topUpAmountController.value.text, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.topUpAmountController.value.text, + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: + controller + .topUpAmountController + .value + .text, + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } } else { - ShowToastDialog.showToast("${'Please Enter minimum amount of'.tr()} ${Constant.amountShow(amount: Constant.minimumAmountToDeposit)}"); + ShowToastDialog.showToast( + "${'Please Enter minimum amount of'.tr()} ${Constant.amountShow(amount: Constant.minimumAmountToDeposit)}", + ); } } }, @@ -141,7 +323,12 @@ class PaymentListScreen extends StatelessWidget { ); } - Obx cardDecoration(WalletController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + WalletController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), @@ -154,22 +341,35 @@ class PaymentListScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), + child: Image.asset(image), + ), ), const SizedBox(width: 10), Expanded( child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart b/lib/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart index 959eb23..ffa4627 100644 --- a/lib/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart +++ b/lib/screen_ui/multi_vendor_service/wallet_screen/wallet_screen.dart @@ -23,7 +23,7 @@ import '../../rental_service/rental_order_details_screen.dart'; import '../order_list_screen/order_details_screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class WalletScreen extends StatelessWidget { const WalletScreen({super.key}); @@ -36,7 +36,8 @@ class WalletScreen extends StatelessWidget { init: WalletController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, body: controller.isLoading.value ? Constant.loader() @@ -49,12 +50,30 @@ class WalletScreen extends StatelessWidget { children: [ Image.asset("assets/images/login.gif", height: 120), const SizedBox(height: 12), - Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "Please Log In to Continue".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -71,7 +90,9 @@ class WalletScreen extends StatelessWidget { ), ) : Padding( - padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top), + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top, + ), child: Column( children: [ Column( @@ -79,20 +100,39 @@ class WalletScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Row( children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "My Wallet".tr(), - style: TextStyle(fontSize: 24, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 24, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w500, + ), ), Text( - "Keep track of your balance, transactions, and payment methods all in one place.".tr(), - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400), + "Keep track of your balance, transactions, and payment methods all in one place." + .tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + ), ), ], ), @@ -102,34 +142,66 @@ class WalletScreen extends StatelessWidget { ), const SizedBox(height: 20), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), child: Container( decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20)), - image: DecorationImage(image: AssetImage("assets/images/wallet.png"), fit: BoxFit.fill), + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + image: DecorationImage( + image: AssetImage( + "assets/images/wallet.png", + ), + fit: BoxFit.fill, + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: Column( children: [ Text( "My Wallet".tr(), maxLines: 1, style: TextStyle( - color: isDark ? AppThemeData.primary100 : AppThemeData.primary100, + color: + isDark + ? AppThemeData.primary100 + : AppThemeData.primary100, fontSize: 16, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.regular, ), ), Text( - Constant.amountShow(amount: controller.userModel.value.walletAmount.toString()), + Constant.amountShow( + amount: + controller + .userModel + .value + .walletAmount + .toString(), + ), maxLines: 1, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 40, overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + fontSize: 40, + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), Padding( - padding: const EdgeInsets.symmetric(horizontal: 80), + padding: const EdgeInsets.symmetric( + horizontal: 80, + ), child: RoundedButtonFill( title: "Top up".tr(), color: AppThemeData.warning300, @@ -149,15 +221,30 @@ class WalletScreen extends StatelessWidget { Expanded( child: controller.walletTransactionList.isEmpty - ? Constant.showEmptyView(message: "Transaction not found".tr()) + ? Constant.showEmptyView( + message: "Transaction not found".tr(), + ) : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: ListView.builder( padding: EdgeInsets.zero, - itemCount: controller.walletTransactionList.length, + itemCount: + controller + .walletTransactionList + .length, itemBuilder: (context, index) { - WalletTransactionModel walletTractionModel = controller.walletTransactionList[index]; - return transactionCard(controller, isDark, walletTractionModel); + WalletTransactionModel + walletTractionModel = + controller + .walletTransactionList[index]; + return transactionCard( + controller, + isDark, + walletTractionModel, + ); }, ), ), @@ -170,32 +257,54 @@ class WalletScreen extends StatelessWidget { ); } - Column transactionCard(WalletController controller, isDark, WalletTransactionModel transactionModel) { + Column transactionCard( + WalletController controller, + isDark, + WalletTransactionModel transactionModel, + ) { return Column( children: [ InkWell( onTap: () async { final orderId = transactionModel.orderId.toString(); - final orderData = await FireStoreUtils.getOrderByIdFromAllCollections(orderId); + final orderData = + await FireStoreUtils.getOrderByIdFromAllCollections(orderId); if (orderData != null) { final collection = orderData['collection_name']; switch (collection) { case CollectionName.parcelOrders: - Get.to(const ParcelOrderDetails(), arguments: ParcelOrderModel.fromJson(orderData)); + Get.to( + const ParcelOrderDetails(), + arguments: ParcelOrderModel.fromJson(orderData), + ); break; case CollectionName.providerOrders: - Get.to(const OnDemandOrderDetailsScreen(), arguments: OnProviderOrderModel.fromJson(orderData)); + Get.to( + const OnDemandOrderDetailsScreen(), + arguments: OnProviderOrderModel.fromJson(orderData), + ); break; case CollectionName.rentalOrders: - Get.to(() => RentalOrderDetailsScreen(), arguments: RentalOrderModel.fromJson(orderData)); + Get.to( + () => RentalOrderDetailsScreen(), + arguments: RentalOrderModel.fromJson(orderData), + ); break; case CollectionName.rides: - Get.to(const CabOrderDetails(), arguments: {"cabOrderModel": CabOrderModel.fromJson(orderData)}); + Get.to( + const CabOrderDetails(), + arguments: { + "cabOrderModel": CabOrderModel.fromJson(orderData), + }, + ); break; case CollectionName.vendorOrders: - Get.to(const OrderDetailsScreen(), arguments: {"orderModel": OrderModel.fromJson(orderData)}); + Get.to( + const OrderDetailsScreen(), + arguments: {"orderModel": OrderModel.fromJson(orderData)}, + ); break; default: ShowToastDialog.showToast("Order details not available".tr()); @@ -220,14 +329,31 @@ class WalletScreen extends StatelessWidget { children: [ Container( decoration: ShapeDecoration( - shape: RoundedRectangleBorder(side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100), borderRadius: BorderRadius.circular(8)), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData.grey800 + : AppThemeData.grey100, + ), + borderRadius: BorderRadius.circular(8), + ), ), child: Padding( padding: const EdgeInsets.all(16), child: transactionModel.isTopup == false - ? SvgPicture.asset("assets/icons/ic_debit.svg", height: 16, width: 16) - : SvgPicture.asset("assets/icons/ic_credit.svg", height: 16, width: 16), + ? SvgPicture.asset( + "assets/icons/ic_debit.svg", + height: 16, + width: 16, + ) + : SvgPicture.asset( + "assets/icons/ic_credit.svg", + height: 16, + width: 16, + ), ), ), const SizedBox(width: 10), @@ -240,19 +366,44 @@ class WalletScreen extends StatelessWidget { Expanded( child: Text( transactionModel.note.toString(), - style: TextStyle(fontSize: 16, fontFamily: AppThemeData.semiBold, fontWeight: FontWeight.w600, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + style: TextStyle( + fontSize: 16, + fontFamily: AppThemeData.semiBold, + fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ), Text( - Constant.amountShow(amount: transactionModel.amount.toString()), - style: TextStyle(fontSize: 16, fontFamily: AppThemeData.medium, color: transactionModel.isTopup == true ? AppThemeData.success400 : AppThemeData.danger300), + Constant.amountShow( + amount: transactionModel.amount.toString(), + ), + style: TextStyle( + fontSize: 16, + fontFamily: AppThemeData.medium, + color: + transactionModel.isTopup == true + ? AppThemeData.success400 + : AppThemeData.danger300, + ), ), ], ), const SizedBox(height: 2), Text( Constant.timestampToDateTime(transactionModel.date!), - style: TextStyle(fontSize: 12, fontFamily: AppThemeData.medium, fontWeight: FontWeight.w500, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700), + style: TextStyle( + fontSize: 12, + fontFamily: AppThemeData.medium, + fontWeight: FontWeight.w500, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + ), ), ], ), @@ -261,10 +412,30 @@ class WalletScreen extends StatelessWidget { ), ), ), - Padding(padding: const EdgeInsets.symmetric(vertical: 5), child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 5), + child: MySeparator( + color: isDark ? AppThemeData.grey700 : AppThemeData.grey200, + ), + ), ], ); } } -enum PaymentGateway {payme, click, payFast, mercadoPago, paypal, stripe, flutterWave, payStack, razorpay, cod, wallet, midTrans, orangeMoney, xendit } +enum PaymentGateway { + payme, + click, + payFast, + mercadoPago, + paypal, + stripe, + flutterWave, + payStack, + razorpay, + cod, + wallet, + midTrans, + orangeMoney, + xendit, +} diff --git a/lib/screen_ui/on_boarding_screen/on_boarding_screen.dart b/lib/screen_ui/on_boarding_screen/on_boarding_screen.dart index e693647..1f87e22 100644 --- a/lib/screen_ui/on_boarding_screen/on_boarding_screen.dart +++ b/lib/screen_ui/on_boarding_screen/on_boarding_screen.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/assets.dart'; import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/on_boarding_controller.dart'; import '../../themes/app_them_data.dart'; import '../../utils/network_image_widget.dart'; @@ -25,7 +25,10 @@ class OnboardingScreen extends StatelessWidget { Image.asset(AppAssets.onBoardingBG, fit: BoxFit.cover), SafeArea( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 20, + ), child: Column( children: [ const SizedBox(height: 20), @@ -35,8 +38,18 @@ class OnboardingScreen extends StatelessWidget { text: TextSpan( style: AppThemeData.regularTextStyle(fontSize: 14), children: [ - TextSpan(text: "${controller.currentPage.value + 1}", style: AppThemeData.regularTextStyle(color: AppThemeData.grey800)), - TextSpan(text: "/$pageCount", style: AppThemeData.regularTextStyle(color: AppThemeData.grey400)), + TextSpan( + text: "${controller.currentPage.value + 1}", + style: AppThemeData.regularTextStyle( + color: AppThemeData.grey800, + ), + ), + TextSpan( + text: "/$pageCount", + style: AppThemeData.regularTextStyle( + color: AppThemeData.grey400, + ), + ), ], ), ), @@ -52,11 +65,28 @@ class OnboardingScreen extends StatelessWidget { return SingleChildScrollView( child: Column( children: [ - Text(item.title ?? '', style: AppThemeData.boldTextStyle(color: AppThemeData.grey900), textAlign: TextAlign.center), + Text( + item.title ?? '', + style: AppThemeData.boldTextStyle( + color: AppThemeData.grey900, + ), + textAlign: TextAlign.center, + ), const SizedBox(height: 5), - Text(item.description ?? '', style: AppThemeData.boldTextStyle(color: AppThemeData.grey500, fontSize: 14), textAlign: TextAlign.center), + Text( + item.description ?? '', + style: AppThemeData.boldTextStyle( + color: AppThemeData.grey500, + fontSize: 14, + ), + textAlign: TextAlign.center, + ), const SizedBox(height: 40), - NetworkImageWidget(imageUrl: item.image ?? '', width: double.infinity, height: 500), + NetworkImageWidget( + imageUrl: item.image ?? '', + width: double.infinity, + height: 500, + ), ], ), ); @@ -74,7 +104,14 @@ class OnboardingScreen extends StatelessWidget { ) : Row( children: [ - Expanded(child: RoundedButtonFill(title: "Skip".tr(), onPress: () => _finish(), color: AppThemeData.grey50, textColor: AppThemeData.grey900)), + Expanded( + child: RoundedButtonFill( + title: "Skip".tr(), + onPress: () => _finish(), + color: AppThemeData.grey50, + textColor: AppThemeData.grey900, + ), + ), const SizedBox(width: 20), Expanded( child: RoundedButtonFill( diff --git a/lib/screen_ui/on_demand_service/favourite_ondemand_screen.dart b/lib/screen_ui/on_demand_service/favourite_ondemand_screen.dart index 527dfbf..e9fe212 100644 --- a/lib/screen_ui/on_demand_service/favourite_ondemand_screen.dart +++ b/lib/screen_ui/on_demand_service/favourite_ondemand_screen.dart @@ -11,7 +11,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class FavouriteOndemandScreen extends StatelessWidget { const FavouriteOndemandScreen({super.key}); @@ -24,7 +24,8 @@ class FavouriteOndemandScreen extends StatelessWidget { init: FavouriteOndemmandController(), builder: (controller) { return Scaffold( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: AppThemeData.onDemand300, @@ -33,7 +34,15 @@ class FavouriteOndemandScreen extends StatelessWidget { child: Row( children: [ const SizedBox(width: 10), - Text("Favourite Services".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey900 : AppThemeData.grey900, fontSize: 20)), + Text( + "Favourite Services".tr(), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + color: + isDark ? AppThemeData.grey900 : AppThemeData.grey900, + fontSize: 20, + ), + ), ], ), ), @@ -50,12 +59,30 @@ class FavouriteOndemandScreen extends StatelessWidget { children: [ Image.asset("assets/images/login.gif", height: 120), const SizedBox(height: 12), - Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "Please Log In to Continue".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -72,10 +99,15 @@ class FavouriteOndemandScreen extends StatelessWidget { ), ) : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: controller.lstFav.isEmpty - ? Constant.showEmptyView(message: "Favourite Service not found.".tr()) + ? Constant.showEmptyView( + message: "Favourite Service not found.".tr(), + ) : ListView.builder( shrinkWrap: true, padding: EdgeInsets.zero, @@ -83,86 +115,231 @@ class FavouriteOndemandScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), itemCount: controller.lstFav.length, itemBuilder: (context, index) { - return FutureBuilder>( - future: FireStoreUtils.getCurrentProviderService(controller.lstFav[index]), + return FutureBuilder< + List + >( + future: + FireStoreUtils.getCurrentProviderService( + controller.lstFav[index], + ), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); + if (snapshot.connectionState == + ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator(), + ); } - if (!snapshot.hasData || snapshot.data == null || snapshot.data!.isEmpty) { + if (!snapshot.hasData || + snapshot.data == null || + snapshot.data!.isEmpty) { return const SizedBox(); // or a placeholder widget } - final provider = snapshot.data!.first; // safer way than [0] + final provider = + snapshot + .data! + .first; // safer way than [0] return GestureDetector( onTap: () { - Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': provider}); + Get.to( + () => OnDemandDetailsScreen(), + arguments: { + 'providerModel': provider, + }, + ); }, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 5, + ), child: Container( - height: MediaQuery.of(context).size.height * 0.16, + height: + MediaQuery.of( + context, + ).size.height * + 0.16, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1), - color: isDark ? AppThemeData.grey900 : Colors.white, + borderRadius: BorderRadius.circular( + 10, + ), + border: Border.all( + color: + isDark + ? AppThemeData.grey500 + : Colors.grey.shade100, + width: 1, + ), + color: + isDark + ? AppThemeData.grey900 + : Colors.white, ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), topLeft: Radius.circular(10)), + borderRadius: + const BorderRadius.only( + bottomLeft: + Radius.circular(10), + topLeft: Radius.circular( + 10, + ), + ), child: CachedNetworkImage( - imageUrl: provider.photos.isNotEmpty ? provider.photos.first : Constant.placeHolderImage, - height: MediaQuery.of(context).size.height * 0.16, + imageUrl: + provider.photos.isNotEmpty + ? provider + .photos + .first + : Constant + .placeHolderImage, + height: + MediaQuery.of( + context, + ).size.height * + 0.16, width: 110, fit: BoxFit.cover, - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), + errorWidget: + ( + context, + url, + error, + ) => Image.network( + Constant + .placeHolderImage, + fit: BoxFit.cover, + ), ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Expanded( child: Text( - provider.title ?? "", + provider.title ?? + "", maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black), + overflow: + TextOverflow + .ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: + FontWeight + .bold, + color: + isDark + ? Colors + .white + : Colors + .black, + ), ), ), Obx( () => GestureDetector( - onTap: () => controller.toggleFavourite(provider), + onTap: + () => controller + .toggleFavourite( + provider, + ), child: Icon( - controller.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? Icons.favorite : Icons.favorite_border, + controller + .lstFav + .where( + ( + element, + ) => + element.service_id == + provider.id, + ) + .isNotEmpty + ? Icons + .favorite + : Icons + .favorite_border, size: 24, color: - controller.lstFav.where((element) => element.service_id == provider.id).isNotEmpty - ? AppThemeData.primary300 - : (isDark ? Colors.white38 : Colors.black38), + controller + .lstFav + .where( + ( + element, + ) => + element.service_id == + provider.id, + ) + .isNotEmpty + ? AppThemeData + .primary300 + : (isDark + ? Colors.white38 + : Colors.black38), ), ), ), ], ), - FutureBuilder( - future: controller.getCategory(provider.categoryId ?? ""), + FutureBuilder< + CategoryModel? + >( + future: controller + .getCategory( + provider.categoryId ?? + "", + ), builder: (ctx, snap) { - if (!snap.hasData) return const SizedBox(); - return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 14, color: isDark ? Colors.white : Colors.black)); + if (!snap.hasData) + return const SizedBox(); + return Text( + snap.data?.title ?? + "", + style: TextStyle( + fontSize: 14, + color: + isDark + ? Colors + .white + : Colors + .black, + ), + ); }, ), - _buildPrice(provider, isDark: isDark), + _buildPrice( + provider, + isDark: isDark, + ), _buildRating(provider), ], ), @@ -176,79 +353,231 @@ class FavouriteOndemandScreen extends StatelessWidget { }, ); FutureBuilder>( - future: FireStoreUtils.getCurrentProviderService(controller.lstFav[index]), + future: + FireStoreUtils.getCurrentProviderService( + controller.lstFav[index], + ), builder: (context, snapshot) { return snapshot.data != null ? GestureDetector( onTap: () { - Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': snapshot.data![0]}); + Get.to( + () => OnDemandDetailsScreen(), + arguments: { + 'providerModel': + snapshot.data![0], + }, + ); }, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 5, + ), child: Container( - height: MediaQuery.of(context).size.height * 0.16, + height: + MediaQuery.of( + context, + ).size.height * + 0.16, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1), - color: isDark ? AppThemeData.grey900 : Colors.white, + borderRadius: + BorderRadius.circular(10), + border: Border.all( + color: + isDark + ? AppThemeData.grey500 + : Colors + .grey + .shade100, + width: 1, + ), + color: + isDark + ? AppThemeData.grey900 + : Colors.white, ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), topLeft: Radius.circular(10)), + borderRadius: + const BorderRadius.only( + bottomLeft: + Radius.circular( + 10, + ), + topLeft: + Radius.circular( + 10, + ), + ), child: CachedNetworkImage( - imageUrl: snapshot.data![0].photos.isNotEmpty ? snapshot.data![0].photos[0] : Constant.placeHolderImage, - height: MediaQuery.of(context).size.height * 0.16, + imageUrl: + snapshot + .data![0] + .photos + .isNotEmpty + ? snapshot + .data![0] + .photos[0] + : Constant + .placeHolderImage, + height: + MediaQuery.of( + context, + ).size.height * + 0.16, width: 110, fit: BoxFit.cover, - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), + placeholder: + ( + context, + url, + ) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), + errorWidget: + ( + context, + url, + error, + ) => Image.network( + Constant + .placeHolderImage, + fit: BoxFit.cover, + ), ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Expanded( child: Text( - snapshot.data![0].title ?? "", + snapshot + .data![0] + .title ?? + "", maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black), + overflow: + TextOverflow + .ellipsis, + style: TextStyle( + fontSize: + 18, + fontWeight: + FontWeight + .bold, + color: + isDark + ? Colors.white + : Colors.black, + ), ), ), Obx( () => GestureDetector( - onTap: () => controller.toggleFavourite(snapshot.data![0]), + onTap: + () => controller.toggleFavourite( + snapshot + .data![0], + ), child: Icon( - controller.lstFav.where((element) => element.service_id == snapshot.data![0].id).isNotEmpty - ? Icons.favorite - : Icons.favorite_border, + controller + .lstFav + .where( + ( + element, + ) => + element.service_id == + snapshot.data![0].id, + ) + .isNotEmpty + ? Icons + .favorite + : Icons + .favorite_border, size: 24, color: - controller.lstFav.where((element) => element.service_id == snapshot.data![0].id).isNotEmpty + controller.lstFav + .where( + ( + element, + ) => + element.service_id == + snapshot.data![0].id, + ) + .isNotEmpty ? AppThemeData.primary300 - : (isDark ? Colors.white38 : Colors.black38), + : (isDark + ? Colors.white38 + : Colors.black38), ), ), ), ], ), - FutureBuilder( - future: controller.getCategory(snapshot.data![0].categoryId ?? ""), - builder: (ctx, snap) { - if (!snap.hasData) return const SizedBox(); - return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 14, color: isDark ? Colors.white : Colors.black)); + FutureBuilder< + CategoryModel? + >( + future: controller + .getCategory( + snapshot + .data![0] + .categoryId ?? + "", + ), + builder: ( + ctx, + snap, + ) { + if (!snap.hasData) + return const SizedBox(); + return Text( + snap + .data + ?.title ?? + "", + style: TextStyle( + fontSize: 14, + color: + isDark + ? Colors + .white + : Colors + .black, + ), + ); }, ), - _buildPrice(snapshot.data![0], isDark: isDark), - _buildRating(snapshot.data![0]), + _buildPrice( + snapshot.data![0], + isDark: isDark, + ), + _buildRating( + snapshot.data![0], + ), ], ), ), @@ -272,20 +601,38 @@ class FavouriteOndemandScreen extends StatelessWidget { Widget _buildPrice(ProviderServiceModel provider, {bool isDark = false}) { if (provider.disPrice == "" || provider.disPrice == "0") { return Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.price) + : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : AppThemeData.primary300, + ), ); } else { return Row( children: [ Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.disPrice ?? '0') + : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : AppThemeData.primary300, + ), ), const SizedBox(width: 5), Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', - style: const TextStyle(fontSize: 12, color: Colors.grey, decoration: TextDecoration.lineThrough), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.price) + : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', + style: const TextStyle( + fontSize: 12, + color: Colors.grey, + decoration: TextDecoration.lineThrough, + ), ), ], ); @@ -298,14 +645,24 @@ class FavouriteOndemandScreen extends StatelessWidget { rating = (provider.reviewsSum ?? 0) / (provider.reviewsCount ?? 1); } return Container( - decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)), + decoration: BoxDecoration( + color: AppThemeData.warning400, + borderRadius: BorderRadius.circular(16), + ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.star, size: 16, color: Colors.white), const SizedBox(width: 3), - Text(rating.toStringAsFixed(1), style: const TextStyle(letterSpacing: 0.5, fontSize: 12, color: Colors.white)), + Text( + rating.toStringAsFixed(1), + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 12, + color: Colors.white, + ), + ), ], ), ); diff --git a/lib/screen_ui/on_demand_service/my_booking_on_demand_screen.dart b/lib/screen_ui/on_demand_service/my_booking_on_demand_screen.dart index 5b61b49..24eae6e 100644 --- a/lib/screen_ui/on_demand_service/my_booking_on_demand_screen.dart +++ b/lib/screen_ui/on_demand_service/my_booking_on_demand_screen.dart @@ -1,7 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../../constant/constant.dart'; import '../../controllers/my_booking_on_demand_controller.dart'; @@ -24,13 +24,24 @@ class MyBookingOnDemandScreen extends StatelessWidget { builder: (controller) { return DefaultTabController( length: controller.tabTitles.length, - initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value), + initialIndex: controller.tabTitles.indexOf( + controller.selectedTab.value, + ), child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: AppThemeData.primary300, centerTitle: false, - title: Padding(padding: const EdgeInsets.only(bottom: 10), child: Text("Booking History".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900))), + title: Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Text( + "Booking History".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + ), bottom: PreferredSize( preferredSize: const Size.fromHeight(48), child: TabBar( @@ -41,8 +52,15 @@ class MyBookingOnDemandScreen extends StatelessWidget { labelColor: AppThemeData.grey900, unselectedLabelColor: AppThemeData.grey900, labelStyle: AppThemeData.boldTextStyle(fontSize: 16), - unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16), - tabs: controller.tabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(), + unselectedLabelStyle: AppThemeData.mediumTextStyle( + fontSize: 16, + ), + tabs: + controller.tabTitles + .map( + (title) => Tab(child: Center(child: Text(title))), + ) + .toList(), ), ), ), @@ -55,78 +73,217 @@ class MyBookingOnDemandScreen extends StatelessWidget { final orders = controller.getOrdersForTab(title); if (orders.isEmpty) { - return Center(child: Text("No ride found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))); + return Center( + child: Text( + "No ride found".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: orders.length, itemBuilder: (context, index) { - OnProviderOrderModel onProviderOrder = orders[index]; - WorkerModel? worker = controller.getWorker(onProviderOrder.workerId); + OnProviderOrderModel onProviderOrder = + orders[index]; + WorkerModel? worker = controller.getWorker( + onProviderOrder.workerId, + ); return InkWell( onTap: () { - Get.to(() => OnDemandOrderDetailsScreen(), arguments: onProviderOrder); + Get.to( + () => OnDemandOrderDetailsScreen(), + arguments: onProviderOrder, + ); }, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 5, + vertical: 5, + ), margin: const EdgeInsets.only(bottom: 15), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1), - color: isDark ? AppThemeData.grey500 : Colors.white, + border: Border.all( + color: + isDark + ? AppThemeData.grey500 + : Colors.grey.shade100, + width: 1, + ), + color: + isDark + ? AppThemeData.grey500 + : Colors.white, ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), child: CachedNetworkImage( - imageUrl: onProviderOrder.provider.photos.first, + imageUrl: + onProviderOrder + .provider + .photos + .first, height: 80, width: 80, imageBuilder: - (context, imageProvider) => - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), + ( + context, + imageProvider, + ) => Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 10, + ), + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), errorWidget: - (context, url, error) => ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Image.network(Constant.placeHolderImage, fit: BoxFit.cover, cacheHeight: 80, cacheWidth: 80), + ( + context, + url, + error, + ) => ClipRRect( + borderRadius: + BorderRadius.circular( + 10, + ), + child: Image.network( + Constant + .placeHolderImage, + fit: BoxFit.cover, + cacheHeight: 80, + cacheWidth: 80, + ), ), fit: BoxFit.cover, ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: + const EdgeInsets.symmetric( + horizontal: 20, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), - decoration: BoxDecoration(color: AppThemeData.info50, border: Border.all(color: AppThemeData.info300), borderRadius: BorderRadius.circular(12)), - child: Text(onProviderOrder.status, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)), - ), - Padding( - padding: const EdgeInsets.only(top: 6), + padding: + const EdgeInsets.symmetric( + vertical: 6, + horizontal: 12, + ), + decoration: BoxDecoration( + color: + AppThemeData.info50, + border: Border.all( + color: + AppThemeData + .info300, + ), + borderRadius: + BorderRadius.circular( + 12, + ), + ), child: Text( - onProviderOrder.provider.title.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + onProviderOrder.status, + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + AppThemeData + .info500, + ), + ), + ), + Padding( + padding: + const EdgeInsets.only( + top: 6, + ), + child: Text( + onProviderOrder + .provider + .title + .toString(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), + ), + Padding( + padding: + const EdgeInsets.only( + top: 6, + ), + child: buildPriceText( + onProviderOrder, ), ), - Padding(padding: const EdgeInsets.only(top: 6), child: buildPriceText(onProviderOrder)), const SizedBox(height: 6), - if (onProviderOrder.status != Constant.orderCompleted && - onProviderOrder.status != Constant.orderCancelled && - onProviderOrder.otp != null && - onProviderOrder.otp!.isNotEmpty) + if (onProviderOrder + .status != + Constant + .orderCompleted && + onProviderOrder + .status != + Constant + .orderCancelled && + onProviderOrder.otp != + null && + onProviderOrder + .otp! + .isNotEmpty) Text( "${'OTP :'.tr()} ${onProviderOrder.otp}", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), @@ -136,7 +293,12 @@ class MyBookingOnDemandScreen extends StatelessWidget { ), /// Bottom Details (Date, Provider, Worker) - buildBottomDetails(context, onProviderOrder, isDark, worker), + buildBottomDetails( + context, + onProviderOrder, + isDark, + worker, + ), ], ), ), @@ -152,37 +314,81 @@ class MyBookingOnDemandScreen extends StatelessWidget { } Widget buildPriceText(OnProviderOrderModel order) { - final hasDiscount = order.provider.disPrice != "" && order.provider.disPrice != "0"; - final price = hasDiscount ? order.provider.disPrice.toString() : order.provider.price.toString(); + final hasDiscount = + order.provider.disPrice != "" && order.provider.disPrice != "0"; + final price = + hasDiscount + ? order.provider.disPrice.toString() + : order.provider.price.toString(); return Text( - order.provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: price) : "${Constant.amountShow(amount: price)}/${'hr'.tr()}", - style: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.primary300), + order.provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: price) + : "${Constant.amountShow(amount: price)}/${'hr'.tr()}", + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: AppThemeData.primary300, + ), ); } - Widget buildBottomDetails(BuildContext context, OnProviderOrderModel order, bool isDark, WorkerModel? worker) { + Widget buildBottomDetails( + BuildContext context, + OnProviderOrderModel order, + bool isDark, + WorkerModel? worker, + ) { return Container( margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey100, width: 1), + border: Border.all( + color: isDark ? AppThemeData.grey400 : AppThemeData.grey100, + width: 1, + ), color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Column( children: [ - detailRow("Date & Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.scheduleDateTime!.toDate()), isDark), + detailRow( + "Date & Time", + DateFormat( + 'dd-MMM-yyyy hh:mm a', + ).format(order.scheduleDateTime!.toDate()), + isDark, + ), const Divider(thickness: 1), detailRow("Provider", order.provider.authorName.toString(), isDark), if (order.provider.priceUnit == "Hourly") ...[ - if (order.startTime != null) ...[const Divider(thickness: 1), detailRow("Start Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.startTime!.toDate()), isDark)], - if (order.endTime != null) ...[const Divider(thickness: 1), detailRow("End Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.endTime!.toDate()), isDark)], + if (order.startTime != null) ...[ + const Divider(thickness: 1), + detailRow( + "Start Time", + DateFormat( + 'dd-MMM-yyyy hh:mm a', + ).format(order.startTime!.toDate()), + isDark, + ), + ], + if (order.endTime != null) ...[ + const Divider(thickness: 1), + detailRow( + "End Time", + DateFormat( + 'dd-MMM-yyyy hh:mm a', + ).format(order.endTime!.toDate()), + isDark, + ), + ], ], - if (worker != null) ...[const Divider(thickness: 1), detailRow("Worker", worker.fullName().toString(), isDark)], + if (worker != null) ...[ + const Divider(thickness: 1), + detailRow("Worker", worker.fullName().toString(), isDark), + ], ], ), ), @@ -195,8 +401,20 @@ class MyBookingOnDemandScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(label.tr(), style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(value.tr(), style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + label.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + value.tr(), + style: AppThemeData.regularTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ), ); diff --git a/lib/screen_ui/on_demand_service/on_demand_booking_screen.dart b/lib/screen_ui/on_demand_service/on_demand_booking_screen.dart index d073c77..db6fa1b 100644 --- a/lib/screen_ui/on_demand_service/on_demand_booking_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_booking_screen.dart @@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/theme_controller.dart'; import '../../controllers/on_demand_booking_controller.dart'; @@ -42,12 +42,30 @@ class OnDemandBookingScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Book Service".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Book Service".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -58,13 +76,28 @@ class OnDemandBookingScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // Services Section - Text("Services".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Services".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 10), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), padding: const EdgeInsets.all(8), child: Row( @@ -73,18 +106,60 @@ class OnDemandBookingScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(controller.provider.value?.title ?? '', style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + controller.provider.value?.title ?? '', + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 5), - Text(controller.categoryTitle.value, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - if (controller.provider.value?.priceUnit == "Fixed") ...[ + Text( + controller.categoryTitle.value, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + if (controller.provider.value?.priceUnit == + "Fixed") ...[ const SizedBox(height: 20), Row( children: [ - GestureDetector(onTap: controller.decrementQuantity, child: Icon(Icons.remove_circle_outline, color: AppThemeData.primary300, size: 30)), + GestureDetector( + onTap: controller.decrementQuantity, + child: Icon( + Icons.remove_circle_outline, + color: AppThemeData.primary300, + size: 30, + ), + ), const SizedBox(width: 10), - Text('${controller.quantity.value}', style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + '${controller.quantity.value}', + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(width: 10), - GestureDetector(onTap: controller.incrementQuantity, child: Icon(Icons.add_circle_outline, color: AppThemeData.primary300, size: 30)), + GestureDetector( + onTap: controller.incrementQuantity, + child: Icon( + Icons.add_circle_outline, + color: AppThemeData.primary300, + size: 30, + ), + ), ], ), ], @@ -98,7 +173,15 @@ class OnDemandBookingScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.grey.shade300, - image: controller.provider.value!.photos.isNotEmpty ? DecorationImage(image: NetworkImage(controller.provider.value?.photos.first), fit: BoxFit.cover) : null, + image: + controller.provider.value!.photos.isNotEmpty + ? DecorationImage( + image: NetworkImage( + controller.provider.value?.photos.first, + ), + fit: BoxFit.cover, + ) + : null, ), ), ], @@ -109,8 +192,14 @@ class OnDemandBookingScreen extends StatelessWidget { padding: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), child: Row( mainAxisAlignment: MainAxisAlignment.start, @@ -119,7 +208,16 @@ class OnDemandBookingScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Address".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Address".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), SizedBox(height: 5), InkWell( onTap: () async { @@ -127,20 +225,32 @@ class OnDemandBookingScreen extends StatelessWidget { Get.to(AddressListScreen())!.then((value) { if (value != null) { ShippingAddress shippingAddress = value; - if (Constant.checkZoneCheck(shippingAddress.location!.latitude ?? 0.0, shippingAddress.location!.longitude ?? 0.0)) { - controller.selectedAddress.value = shippingAddress; + if (Constant.checkZoneCheck( + shippingAddress.location!.latitude ?? + 0.0, + shippingAddress.location!.longitude ?? + 0.0, + )) { + controller.selectedAddress.value = + shippingAddress; controller.calculatePrice(); } else { - ShowToastDialog.showToast("Service not available in this area".tr()); + ShowToastDialog.showToast( + "Service not available in this area" + .tr(), + ); } } }); } else { Constant.checkPermission( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); - ShippingAddress shippingAddress = ShippingAddress(); + ShippingAddress shippingAddress = + ShippingAddress(); try { await Geolocator.requestPermission(); @@ -148,43 +258,81 @@ class OnDemandBookingScreen extends StatelessWidget { ShowToastDialog.closeLoader(); if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lat = + firstPlace.coordinates.latitude; + final lng = + firstPlace + .coordinates + .longitude; final address = firstPlace.address; shippingAddress.addressAs = "Home"; - shippingAddress.locality = address.toString(); - shippingAddress.location = UserLocation(latitude: lat, longitude: lng); + shippingAddress.locality = + address.toString(); + shippingAddress + .location = UserLocation( + latitude: lat, + longitude: lng, + ); - controller.selectedAddress.value = shippingAddress; + controller.selectedAddress.value = + shippingAddress; Get.back(); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); - shippingAddress.locality = "Picked from Map"; + shippingAddress.addressAs = + "Home"; + shippingAddress + .location = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, + ); + shippingAddress.locality = + "Picked from Map"; - controller.selectedAddress.value = shippingAddress; + controller.selectedAddress.value = + shippingAddress; } }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { - Placemark placeMark = valuePlaceMaker[0]; - shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { + Placemark placeMark = + valuePlaceMaker[0]; + shippingAddress + .location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; - shippingAddress.locality = currentLocation; + shippingAddress.locality = + currentLocation; }); - controller.selectedAddress.value = shippingAddress; + controller.selectedAddress.value = + shippingAddress; ShowToastDialog.closeLoader(); } }, @@ -193,10 +341,17 @@ class OnDemandBookingScreen extends StatelessWidget { } }, child: Text( - controller.selectedAddress.value.getFullAddress(), + controller.selectedAddress.value + .getFullAddress(), maxLines: 1, overflow: TextOverflow.ellipsis, - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), ], @@ -206,7 +361,12 @@ class OnDemandBookingScreen extends StatelessWidget { ), ), const SizedBox(height: 15), - TextFieldWidget(title: "Description".tr(), hintText: "Enter Description".tr(), controller: controller.descriptionController.value, maxLine: 5), + TextFieldWidget( + title: "Description".tr(), + hintText: "Enter Description".tr(), + controller: controller.descriptionController.value, + maxLine: 5, + ), const SizedBox(height: 10), GestureDetector( onTap: () { @@ -220,13 +380,36 @@ class OnDemandBookingScreen extends StatelessWidget { buttonSingleColor: AppThemeData.primary300, buttonPadding: 10, buttonWidth: 70, - pickerTitle: Text("", style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - pickerTextStyle: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + pickerTitle: Text( + "", + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + backgroundColor: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + pickerTextStyle: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), closeIconColor: isDark ? Colors.white : Colors.black, ).show(context); }, - child: TextFieldWidget(title: "Booking Date & Slot".tr(), hintText: "Choose Date and Time".tr(), controller: controller.dateTimeController.value, enable: false), + child: TextFieldWidget( + title: "Booking Date & Slot".tr(), + hintText: "Choose Date and Time".tr(), + controller: controller.dateTimeController.value, + enable: false, + ), ), const SizedBox(height: 15), controller.provider.value?.priceUnit == "Fixed" @@ -241,7 +424,14 @@ class OnDemandBookingScreen extends StatelessWidget { scrollDirection: Axis.horizontal, itemBuilder: (context, index) { final coupon = controller.couponList[index]; - return GestureDetector(onTap: () => controller.applyCoupon(coupon), child: buildOfferItem(controller, index, isDark)); + return GestureDetector( + onTap: () => controller.applyCoupon(coupon), + child: buildOfferItem( + controller, + index, + isDark, + ), + ); }, ), ) @@ -249,7 +439,16 @@ class OnDemandBookingScreen extends StatelessWidget { buildPromoCode(controller, isDark), Padding( padding: EdgeInsets.symmetric(vertical: 10), - child: Text("Price Detail".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + "Price Detail".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), priceTotalRow(controller, isDark), ], @@ -260,14 +459,23 @@ class OnDemandBookingScreen extends StatelessWidget { ), bottomNavigationBar: Padding( padding: const EdgeInsets.all(20.0), - child: RoundedButtonFill(title: "Confirm".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () => controller.confirmBooking(context)), + child: RoundedButtonFill( + title: "Confirm".tr(), + color: AppThemeData.primary300, + textColor: AppThemeData.grey50, + onPress: () => controller.confirmBooking(context), + ), ), ); }, ); } - Widget buildOfferItem(OnDemandBookingController controller, int index, bool isDark) { + Widget buildOfferItem( + OnDemandBookingController controller, + int index, + bool isDark, + ) { return Obx(() { final coupon = controller.couponList[index]; @@ -275,7 +483,11 @@ class OnDemandBookingScreen extends StatelessWidget { margin: const EdgeInsets.fromLTRB(7, 10, 7, 10), height: 85, child: DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(10), + color: AppThemeData.primary300, + ), child: Padding( padding: const EdgeInsets.fromLTRB(12, 5, 12, 0), child: Column( @@ -284,13 +496,26 @@ class OnDemandBookingScreen extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Image(image: AssetImage('assets/images/offer_icon.png'), height: 25, width: 25), + const Image( + image: AssetImage('assets/images/offer_icon.png'), + height: 25, + width: 25, + ), const SizedBox(width: 10), Container( margin: const EdgeInsets.only(top: 3), child: Text( - coupon.discountType == "Fix Price" ? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}" : "${coupon.discount} ${'% Off'.tr()}", - style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 0.7, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + coupon.discountType == "Fix Price" + ? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}" + : "${coupon.discount} ${'% Off'.tr()}", + style: TextStyle( + fontWeight: FontWeight.bold, + letterSpacing: 0.7, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), ], @@ -299,11 +524,36 @@ class OnDemandBookingScreen extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(coupon.code ?? '', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, letterSpacing: 0.5, color: Colors.orange)), - Container(margin: const EdgeInsets.only(left: 15, right: 15, top: 3), width: 1, color: AppThemeData.grey50), Text( - "valid till ".tr() + controller.getDate(coupon.expiresAt!.toDate().toString()), - style: TextStyle(letterSpacing: 0.5, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + coupon.code ?? '', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + letterSpacing: 0.5, + color: Colors.orange, + ), + ), + Container( + margin: const EdgeInsets.only( + left: 15, + right: 15, + top: 3, + ), + width: 1, + color: AppThemeData.grey50, + ), + Text( + "valid till ".tr() + + controller.getDate( + coupon.expiresAt!.toDate().toString(), + ), + style: TextStyle( + letterSpacing: 0.5, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -321,7 +571,9 @@ class OnDemandBookingScreen extends StatelessWidget { margin: const EdgeInsets.only(top: 10, bottom: 13), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), + border: Border.all( + color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), child: Padding( @@ -332,17 +584,37 @@ class OnDemandBookingScreen extends StatelessWidget { Expanded( child: Row( children: [ - Image.asset("assets/images/reedem.png", height: 50, width: 50), + Image.asset( + "assets/images/reedem.png", + height: 50, + width: 50, + ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Promo Code".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), overflow: TextOverflow.ellipsis), + Text( + "Promo Code".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + overflow: TextOverflow.ellipsis, + ), const SizedBox(height: 5), Text( "Apply promo code".tr(), - style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), overflow: TextOverflow.ellipsis, ), ], @@ -353,7 +625,13 @@ class OnDemandBookingScreen extends StatelessWidget { ), FloatingActionButton( onPressed: () { - Get.bottomSheet(promoCodeSheet(controller, isDark), isScrollControlled: true, isDismissible: true, backgroundColor: Colors.transparent, enableDrag: true); + Get.bottomSheet( + promoCodeSheet(controller, isDark), + isScrollControlled: true, + isDismissible: true, + backgroundColor: Colors.transparent, + enableDrag: true, + ); }, mini: true, backgroundColor: Colors.blueGrey.shade50, @@ -371,7 +649,10 @@ class OnDemandBookingScreen extends StatelessWidget { return Container( padding: EdgeInsets.only(bottom: Get.height / 4.3, left: 25, right: 25), height: Get.height * 0.88, - decoration: BoxDecoration(color: Colors.transparent, border: Border.all(style: BorderStyle.none)), + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(style: BorderStyle.none), + ), child: Column( children: [ InkWell( @@ -379,14 +660,21 @@ class OnDemandBookingScreen extends StatelessWidget { child: Container( height: 45, decoration: BoxDecoration( - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, width: 0.3), + border: Border.all( + color: + isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + width: 0.3, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, shape: BoxShape.circle, ), child: Center( child: Icon( Icons.close, - color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, // ✅ visible color + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, // ✅ visible color size: 28, ), ), @@ -395,40 +683,93 @@ class OnDemandBookingScreen extends StatelessWidget { const SizedBox(height: 25), Expanded( child: Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + ), alignment: Alignment.center, child: SingleChildScrollView( child: Column( children: [ - Container(padding: const EdgeInsets.only(top: 30), child: const Image(image: AssetImage('assets/images/redeem_coupon.png'), width: 100)), Container( - padding: const EdgeInsets.only(top: 20), - child: Text('Redeem Your Coupons'.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)), - ), - Center( - child: Container( - padding: const EdgeInsets.only(top: 10, left: 22, right: 22), - child: Text("Voucher or Coupon code".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + padding: const EdgeInsets.only(top: 30), + child: const Image( + image: AssetImage('assets/images/redeem_coupon.png'), + width: 100, ), ), Container( - padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + padding: const EdgeInsets.only(top: 20), + child: Text( + 'Redeem Your Coupons'.tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), + ), + Center( + child: Container( + padding: const EdgeInsets.only( + top: 10, + left: 22, + right: 22, + ), + child: Text( + "Voucher or Coupon code".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), + ), + Container( + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 20, + ), child: DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(12), color: AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(12), + color: AppThemeData.primary300, + ), child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(12)), + borderRadius: const BorderRadius.all( + Radius.circular(12), + ), child: Container( padding: const EdgeInsets.all(20), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, alignment: Alignment.center, child: TextFormField( textAlign: TextAlign.center, - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), controller: controller.couponTextController.value, decoration: InputDecoration( border: InputBorder.none, hintText: "Write Coupon Code".tr(), - hintStyle: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400), + hintStyle: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey400, + ), ), ), ), @@ -436,21 +777,34 @@ class OnDemandBookingScreen extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.only(top: 30, bottom: 30, left: 15, right: 15), + padding: const EdgeInsets.only( + top: 30, + bottom: 30, + left: 15, + right: 15, + ), child: RoundedButtonFill( title: "REDEEM NOW".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () { - final inputCode = controller.couponTextController.value.text.trim().toLowerCase(); + final inputCode = + controller.couponTextController.value.text + .trim() + .toLowerCase(); - final matchingCoupon = controller.couponList.firstWhereOrNull((c) => c.code?.toLowerCase() == inputCode); + final matchingCoupon = controller.couponList + .firstWhereOrNull( + (c) => c.code?.toLowerCase() == inputCode, + ); if (matchingCoupon != null) { controller.applyCoupon(matchingCoupon); Get.back(); } else { - ShowToastDialog.showToast("Applied coupon not valid.".tr()); + ShowToastDialog.showToast( + "Applied coupon not valid.".tr(), + ); } }, ), @@ -470,14 +824,22 @@ class OnDemandBookingScreen extends StatelessWidget { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), + border: Border.all( + color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), child: Column( children: [ const SizedBox(height: 5), - rowText("Price".tr(), Constant.amountShow(amount: controller.price.value.toString()), isDark), - controller.discountAmount.value != 0 ? const Divider() : const SizedBox(), + rowText( + "Price".tr(), + Constant.amountShow(amount: controller.price.value.toString()), + isDark, + ), + controller.discountAmount.value != 0 + ? const Divider() + : const SizedBox(), controller.discountAmount.value != 0 ? Padding( padding: const EdgeInsets.symmetric(horizontal: 10), @@ -490,19 +852,39 @@ class OnDemandBookingScreen extends StatelessWidget { children: [ Text( "${"Discount".tr()} ${controller.discountType.value == 'Percentage' || controller.discountType.value == 'Percent' ? "(${controller.discountLabel.value}%)" : "(${Constant.amountShow(amount: controller.discountLabel.value)})"}", - style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: TextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + controller.offerCode.value, + style: TextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), - Text(controller.offerCode.value, style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ], ), ), - Text("(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})", style: const TextStyle(color: Colors.red)), + Text( + "(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})", + style: const TextStyle(color: Colors.red), + ), ], ), ) : const SizedBox(), const Divider(), - rowText("SubTotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark), + rowText( + "SubTotal".tr(), + Constant.amountShow(amount: controller.subTotal.value.toString()), + isDark, + ), const Divider(), ListView.builder( itemCount: Constant.taxList.length, @@ -513,19 +895,39 @@ class OnDemandBookingScreen extends StatelessWidget { return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 10, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( "${taxModel.title} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})", - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), Text( - Constant.amountShow(amount: Constant.getTaxValue(amount: controller.subTotal.value.toString(), taxModel: taxModel).toString()), - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + Constant.getTaxValue( + amount: + controller.subTotal.value.toString(), + taxModel: taxModel, + ).toString(), + ), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -535,7 +937,13 @@ class OnDemandBookingScreen extends StatelessWidget { ); }, ), - rowText("Total Amount".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark), + rowText( + "Total Amount".tr(), + Constant.amountShow( + amount: controller.totalAmount.value.toString(), + ), + isDark, + ), const SizedBox(height: 5), ], ), @@ -549,8 +957,18 @@ class OnDemandBookingScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(value.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title.tr(), + style: AppThemeData.mediumTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + value.tr(), + style: AppThemeData.mediumTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ), ); diff --git a/lib/screen_ui/on_demand_service/on_demand_category_screen.dart b/lib/screen_ui/on_demand_service/on_demand_category_screen.dart index 80daba8..a5e20c6 100644 --- a/lib/screen_ui/on_demand_service/on_demand_category_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_category_screen.dart @@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:customer/screen_ui/on_demand_service/view_category_service_screen.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/on_demand_category_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -33,8 +33,20 @@ class OnDemandCategoryScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -42,12 +54,22 @@ class OnDemandCategoryScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Explore services".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), Text( - "Explore services tailored for you—quick, easy, and personalized.".tr(), + "Explore services".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + Text( + "Explore services tailored for you—quick, easy, and personalized." + .tr(), maxLines: 1, overflow: TextOverflow.ellipsis, - style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), ), ], ), @@ -60,7 +82,10 @@ class OnDemandCategoryScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + padding: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 15, + ), child: SingleChildScrollView( child: Column( children: [ @@ -71,9 +96,17 @@ class OnDemandCategoryScreen extends StatelessWidget { itemCount: controller.categories.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + ), itemBuilder: (context, index) { - return categoriesCell(context, controller.categories[index], index, isDark); + return categoriesCell( + context, + controller.categories[index], + index, + isDark, + ); }, ), ], @@ -85,16 +118,42 @@ class OnDemandCategoryScreen extends StatelessWidget { ); } - Widget categoriesCell(BuildContext context, CategoryModel category, int index, bool isDark) { + Widget categoriesCell( + BuildContext context, + CategoryModel category, + int index, + bool isDark, + ) { return GestureDetector( onTap: () { - Get.to(() => ViewCategoryServiceListScreen(), arguments: {'categoryId': category.id, 'categoryTitle': category.title}); + Get.to( + () => ViewCategoryServiceListScreen(), + arguments: { + 'categoryId': category.id, + 'categoryTitle': category.title, + }, + ); }, child: Column( children: [ - ClipRRect(borderRadius: BorderRadius.circular(12), child: CachedNetworkImage(imageUrl: category.image ?? "", height: 60, width: 60, fit: BoxFit.cover)), + ClipRRect( + borderRadius: BorderRadius.circular(12), + child: CachedNetworkImage( + imageUrl: category.image ?? "", + height: 60, + width: 60, + fit: BoxFit.cover, + ), + ), const SizedBox(height: 5), - Text(category.title ?? "", style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), textAlign: TextAlign.center), + Text( + category.title ?? "", + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + textAlign: TextAlign.center, + ), ], ), ); diff --git a/lib/screen_ui/on_demand_service/on_demand_dashboard_screen.dart b/lib/screen_ui/on_demand_service/on_demand_dashboard_screen.dart index 47b5f9a..60749e6 100644 --- a/lib/screen_ui/on_demand_service/on_demand_dashboard_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_dashboard_screen.dart @@ -5,8 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../controllers/on_demand_dashboard_controller.dart'; class OnDemandDashboardScreen extends StatelessWidget { @@ -27,12 +26,19 @@ class OnDemandDashboardScreen extends StatelessWidget { showUnselectedLabels: true, showSelectedLabels: true, selectedFontSize: 12, - selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), - unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), + selectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), + unselectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), currentIndex: controller.selectedIndex.value, - backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - selectedItemColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - unselectedItemColor: isDark ? AppThemeData.grey300 : AppThemeData.grey600, + backgroundColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + selectedItemColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, + unselectedItemColor: + isDark ? AppThemeData.grey300 : AppThemeData.grey600, onTap: (int index) { if (index == 0) { Get.put(CabDashboardController()); @@ -42,18 +48,72 @@ class OnDemandDashboardScreen extends StatelessWidget { items: Constant.walletSetting == false ? [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_cab.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_booking_cab.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ] : [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_cab.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_fav.svg", + label: 'Favourites'.tr(), + controller: controller, + ), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_wallet_cab.svg", label: 'Wallet'.tr(), controller: controller), - navigationBarItem(isDark, index: 4, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_booking_cab.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_wallet_cab.svg", + label: 'Wallet'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 4, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ], ), ); @@ -62,7 +122,13 @@ class OnDemandDashboardScreen extends StatelessWidget { }); } - BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required OnDemandDashboardController controller}) { + BottomNavigationBarItem navigationBarItem( + isDark, { + required int index, + required String label, + required String assetIcon, + required OnDemandDashboardController controller, + }) { return BottomNavigationBarItem( icon: Padding( padding: const EdgeInsets.symmetric(vertical: 5), diff --git a/lib/screen_ui/on_demand_service/on_demand_details_screen.dart b/lib/screen_ui/on_demand_service/on_demand_details_screen.dart index 31b8c6c..dcfbca1 100644 --- a/lib/screen_ui/on_demand_service/on_demand_details_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_details_screen.dart @@ -4,7 +4,7 @@ import 'package:customer/screen_ui/on_demand_service/provider_screen.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../../controllers/theme_controller.dart'; import '../../models/provider_serivce_model.dart'; @@ -25,7 +25,13 @@ class OnDemandDetailsScreen extends StatelessWidget { init: OnDemandDetailsController(), builder: (controller) { return Scaffold( - body: buildSliverScrollView(context, controller, controller.provider, controller.userModel, isDark), + body: buildSliverScrollView( + context, + controller, + controller.provider, + controller.userModel, + isDark, + ), bottomNavigationBar: controller.isOpen.value == false ? SizedBox() @@ -43,9 +49,20 @@ class OnDemandDetailsScreen extends StatelessWidget { if (Constant.userModel == null) { Get.offAll(const LoginScreen()); } else { - print("providerModel ::::::::${controller.provider.title ?? 'No provider'}"); - print("categoryTitle ::::::: ${controller.categoryTitle.value}"); - Get.to(() => OnDemandBookingScreen(), arguments: {'providerModel': controller.provider, 'categoryTitle': controller.categoryTitle.value}); + print( + "providerModel ::::::::${controller.provider.title ?? 'No provider'}", + ); + print( + "categoryTitle ::::::: ${controller.categoryTitle.value}", + ); + Get.to( + () => OnDemandBookingScreen(), + arguments: { + 'providerModel': controller.provider, + 'categoryTitle': + controller.categoryTitle.value, + }, + ); } }, ), @@ -57,7 +74,13 @@ class OnDemandDetailsScreen extends StatelessWidget { ); } - SingleChildScrollView buildSliverScrollView(BuildContext context, OnDemandDetailsController controller, ProviderServiceModel provider, user, isDark) { + SingleChildScrollView buildSliverScrollView( + BuildContext context, + OnDemandDetailsController controller, + ProviderServiceModel provider, + user, + isDark, + ) { final width = MediaQuery.of(context).size.width; final height = MediaQuery.of(context).size.height; @@ -68,21 +91,54 @@ class OnDemandDetailsScreen extends StatelessWidget { Stack( children: [ CachedNetworkImage( - imageUrl: provider.photos.isNotEmpty ? provider.photos.first : "", - placeholder: (context, url) => Center(child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.fitWidth), + imageUrl: + provider.photos.isNotEmpty ? provider.photos.first : "", + placeholder: + (context, url) => Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + AppThemeData.primary300, + ), + ), + ), + errorWidget: + (context, url, error) => Image.network( + Constant.placeHolderImage, + fit: BoxFit.fitWidth, + ), fit: BoxFit.fitWidth, width: width, height: height * 0.45, ), - Positioned(top: height * 0.05, left: width * 0.03, child: _circleButton(context, icon: Icons.arrow_back, onTap: () => Get.back())), + Positioned( + top: height * 0.05, + left: width * 0.03, + child: _circleButton( + context, + icon: Icons.arrow_back, + onTap: () => Get.back(), + ), + ), Positioned( top: height * 0.05, right: width * 0.03, child: Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(40), color: controller.isOpen.value ? Colors.green : Colors.red), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - child: Text(controller.isOpen.value ? "Open".tr() : "Close".tr(), style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14)), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: controller.isOpen.value ? Colors.green : Colors.red, + ), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + child: Text( + controller.isOpen.value ? "Open".tr() : "Close".tr(), + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.white, + fontSize: 14, + ), + ), ), ), ], @@ -105,27 +161,66 @@ class OnDemandDetailsScreen extends StatelessWidget { Expanded( child: Text( provider.title.toString(), - style: TextStyle(fontSize: 20, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black), + style: TextStyle( + fontSize: 20, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black, + ), ), ), Row( children: [ provider.disPrice == "" || provider.disPrice == "0" ? Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price ?? '0') : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}', - style: TextStyle(fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow( + amount: provider.price ?? '0', + ) + : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}', + style: TextStyle( + fontSize: 18, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.bold, + color: + isDark + ? Colors.white + : AppThemeData.primary300, + ), ) : Row( children: [ Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice ?? '0')}/${'hr'.tr()}', - style: TextStyle(fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow( + amount: provider.disPrice ?? '0', + ) + : '${Constant.amountShow(amount: provider.disPrice ?? '0')}/${'hr'.tr()}', + style: TextStyle( + fontSize: 18, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.bold, + color: + isDark + ? Colors.white + : AppThemeData.primary300, + ), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price ?? '0') : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}', - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.grey, decoration: TextDecoration.lineThrough), + provider.priceUnit == 'Fixed' + ? Constant.amountShow( + amount: provider.price ?? '0', + ) + : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}', + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + color: Colors.grey, + decoration: + TextDecoration.lineThrough, + ), ), ), ], @@ -139,23 +234,51 @@ class OnDemandDetailsScreen extends StatelessWidget { Expanded( child: Padding( padding: const EdgeInsets.symmetric(vertical: 5), - child: Text(categoryTitle, style: TextStyle(fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? Colors.white : Colors.black)), + child: Text( + categoryTitle, + style: TextStyle( + fontSize: 14, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + color: isDark ? Colors.white : Colors.black, + ), + ), ), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Row( children: [ - const Icon(Icons.star, size: 16, color: AppThemeData.warning400), + const Icon( + Icons.star, + size: 16, + color: AppThemeData.warning400, + ), const SizedBox(width: 3), Text( - provider.reviewsCount != 0 ? ((provider.reviewsSum ?? 0.0) / (provider.reviewsCount ?? 0.0)).toStringAsFixed(1) : '0', - style: const TextStyle(letterSpacing: 0.5, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: AppThemeData.warning400), + provider.reviewsCount != 0 + ? ((provider.reviewsSum ?? 0.0) / + (provider.reviewsCount ?? 0.0)) + .toStringAsFixed(1) + : '0', + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 16, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + color: AppThemeData.warning400, + ), ), const SizedBox(width: 10), Text( "(${provider.reviewsCount} ${'Reviews'.tr()})", - style: TextStyle(letterSpacing: 0.5, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: isDark ? Colors.white : Colors.black), + style: TextStyle( + letterSpacing: 0.5, + fontSize: 16, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black, + ), ), ], ), @@ -168,18 +291,40 @@ class OnDemandDetailsScreen extends StatelessWidget { children: [ subCategoryTitle.isNotEmpty ? Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.primary300.withOpacity(0.20)), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppThemeData.primary300.withOpacity( + 0.20, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - child: Text(subCategoryTitle, style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + child: Text( + subCategoryTitle, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + fontFamily: AppThemeData.regular, + color: AppThemeData.primary300, + ), + ), ), ) : Container(), const SizedBox(width: 10), Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.green.withOpacity(0.20)), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.green.withOpacity(0.20), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: InkWell( onTap: () { showModalBottomSheet( @@ -188,10 +333,22 @@ class OnDemandDetailsScreen extends StatelessWidget { context: context, backgroundColor: Colors.transparent, enableDrag: true, - builder: (context) => showTiming(context, controller, isDark), + builder: + (context) => showTiming( + context, + controller, + isDark, + ), ); }, - child: Text("View Timing".tr(), style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.green, letterSpacing: 0.5)), + child: Text( + "View Timing".tr(), + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.green, + letterSpacing: 0.5, + ), + ), ), ), ), @@ -201,14 +358,22 @@ class OnDemandDetailsScreen extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon(Icons.location_on_outlined, color: isDark ? Colors.white : Colors.black, size: 20), + Icon( + Icons.location_on_outlined, + color: isDark ? Colors.white : Colors.black, + size: 20, + ), const SizedBox(width: 5), Expanded( child: Text( provider.address.toString(), maxLines: 2, overflow: TextOverflow.ellipsis, - style: TextStyle(fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? Colors.white : Colors.black), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w400, + color: isDark ? Colors.white : Colors.black, + ), ), ), ], @@ -219,7 +384,11 @@ class OnDemandDetailsScreen extends StatelessWidget { _tabBar(controller), Obx(() { if (controller.tabString.value == "About") { - return aboutTabViewWidget(controller, controller.provider, isDark); + return aboutTabViewWidget( + controller, + controller.provider, + isDark, + ); } else if (controller.tabString.value == "Gallery") { return galleryTabViewWidget(controller); } else { @@ -237,14 +406,35 @@ class OnDemandDetailsScreen extends StatelessWidget { ); } - Widget _circleButton(BuildContext context, {required IconData icon, required VoidCallback onTap}) { + Widget _circleButton( + BuildContext context, { + required IconData icon, + required VoidCallback onTap, + }) { return ClipOval( - child: Container(color: Colors.black.withOpacity(0.7), child: InkWell(onTap: onTap, child: Padding(padding: const EdgeInsets.all(8.0), child: Icon(icon, size: 30, color: Colors.white)))), + child: Container( + color: Colors.black.withOpacity(0.7), + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(icon, size: 30, color: Colors.white), + ), + ), + ), ); } Widget _tabBar(OnDemandDetailsController controller) { - return Obx(() => Row(children: [_tabItem("About", controller), _tabItem("Gallery", controller), _tabItem("Review", controller)])); + return Obx( + () => Row( + children: [ + _tabItem("About", controller), + _tabItem("Gallery", controller), + _tabItem("Review", controller), + ], + ), + ); } Widget _tabItem(String title, OnDemandDetailsController controller) { @@ -253,33 +443,67 @@ class OnDemandDetailsScreen extends StatelessWidget { child: Container( margin: const EdgeInsets.only(right: 10), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - decoration: BoxDecoration(color: controller.tabString.value == title ? AppThemeData.primary300 : Colors.grey.shade200, borderRadius: BorderRadius.circular(10)), - child: Text(title.tr(), style: TextStyle(fontWeight: FontWeight.bold, color: controller.tabString.value == title ? Colors.white : Colors.black)), + decoration: BoxDecoration( + color: + controller.tabString.value == title + ? AppThemeData.primary300 + : Colors.grey.shade200, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + title.tr(), + style: TextStyle( + fontWeight: FontWeight.bold, + color: + controller.tabString.value == title + ? Colors.white + : Colors.black, + ), + ), ), ); } - Widget aboutTabViewWidget(OnDemandDetailsController controller, ProviderServiceModel providerModel, bool isDark) { + Widget aboutTabViewWidget( + OnDemandDetailsController controller, + ProviderServiceModel providerModel, + bool isDark, + ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text((providerModel.description ?? '').tr(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500)), + Text( + (providerModel.description ?? '').tr(), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontSize: 14, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), + ), const SizedBox(height: 10), Obx(() { final user = controller.userModel.value; if (user == null) return const SizedBox(); return InkWell( onTap: () { - Get.to(() => ProviderScreen(), arguments: {'providerId': user.id}); + Get.to( + () => ProviderScreen(), + arguments: {'providerId': user.id}, + ); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1), + border: Border.all( + color: + isDark ? AppThemeData.grey500 : Colors.grey.shade100, + width: 1, + ), color: isDark ? AppThemeData.grey500 : Colors.white, ), child: Padding( @@ -289,30 +513,86 @@ class OnDemandDetailsScreen extends StatelessWidget { Expanded( child: Row( children: [ - CircleAvatar(radius: 30, backgroundImage: NetworkImage(user.profilePictureURL?.isNotEmpty == true ? user.profilePictureURL! : Constant.placeHolderImage)), + CircleAvatar( + radius: 30, + backgroundImage: NetworkImage( + user.profilePictureURL?.isNotEmpty == true + ? user.profilePictureURL! + : Constant.placeHolderImage, + ), + ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(user.fullName(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.bold)), + Text( + user.fullName(), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), const SizedBox(height: 5), - Text(user.email ?? '', style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14)), + Text( + user.email ?? '', + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontSize: 14, + ), + ), const SizedBox(height: 10), // Rating Box Container( - decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)), - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: AppThemeData.warning400, + borderRadius: BorderRadius.circular(16), + ), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, size: 16, color: Colors.white), + const Icon( + Icons.star, + size: 16, + color: Colors.white, + ), const SizedBox(width: 3), Text( - double.parse(user.reviewsCount.toString()) != 0 - ? (double.parse(user.reviewsSum.toString()) / double.parse(user.reviewsCount.toString())).toStringAsFixed(1) + double.parse( + user.reviewsCount + .toString(), + ) != + 0 + ? (double.parse( + user.reviewsSum + .toString(), + ) / + double.parse( + user.reviewsCount + .toString(), + )) + .toStringAsFixed(1) : '0', - style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white), + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 12, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + color: Colors.white, + ), ), ], ), @@ -348,7 +628,12 @@ class OnDemandDetailsScreen extends StatelessWidget { shrinkWrap: true, padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, mainAxisSpacing: 0, crossAxisSpacing: 8, mainAxisExtent: 180), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + mainAxisSpacing: 0, + crossAxisSpacing: 8, + mainAxisExtent: 180, + ), itemBuilder: (context, index) { final imageUrl = photos[index]; return Padding( @@ -359,9 +644,29 @@ class OnDemandDetailsScreen extends StatelessWidget { imageUrl: imageUrl, height: 60, width: 60, - imageBuilder: (context, imageProvider) => Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), + imageBuilder: + (context, imageProvider) => Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: AlwaysStoppedAnimation( + AppThemeData.primary300, + ), + ), + ), + errorWidget: + (context, url, error) => Image.network( + Constant.placeHolderImage, + fit: BoxFit.cover, + ), fit: BoxFit.cover, ), ), @@ -370,11 +675,24 @@ class OnDemandDetailsScreen extends StatelessWidget { ); } - Widget reviewTabViewWidget(OnDemandDetailsController controller, bool isDark) { + Widget reviewTabViewWidget( + OnDemandDetailsController controller, + bool isDark, + ) { final reviews = controller.ratingService; if (reviews.isEmpty) { - return SizedBox(height: 200, child: Center(child: Text("No review Found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)))); + return SizedBox( + height: 200, + child: Center( + child: Text( + "No review Found".tr(), + style: AppThemeData.mediumTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + ), + ); } return ListView.builder( @@ -390,8 +708,17 @@ class OnDemandDetailsScreen extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( color: isDark ? AppThemeData.grey700 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - shadows: const [BoxShadow(color: Color(0x0A000000), blurRadius: 32, offset: Offset(0, 0), spreadRadius: 0)], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + shadows: const [ + BoxShadow( + color: Color(0x0A000000), + blurRadius: 32, + offset: Offset(0, 0), + spreadRadius: 0, + ), + ], ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -401,26 +728,58 @@ class OnDemandDetailsScreen extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(review.uname ?? '', style: TextStyle(fontSize: 16, letterSpacing: 1, fontWeight: FontWeight.w600, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - review.createdAt != null ? DateFormat('dd MMM').format(review.createdAt!.toDate()) : '', - style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + review.uname ?? '', + style: TextStyle( + fontSize: 16, + letterSpacing: 1, + fontWeight: FontWeight.w600, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + review.createdAt != null + ? DateFormat( + 'dd MMM', + ).format(review.createdAt!.toDate()) + : '', + style: TextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), const SizedBox(height: 4), RatingBar.builder( - initialRating: double.tryParse(review.rating.toString()) ?? 0, + initialRating: + double.tryParse(review.rating.toString()) ?? 0, direction: Axis.horizontal, itemSize: 20, ignoreGestures: true, itemPadding: const EdgeInsets.symmetric(horizontal: 4.0), - itemBuilder: (context, _) => Icon(Icons.star, color: AppThemeData.primary300), + itemBuilder: + (context, _) => + Icon(Icons.star, color: AppThemeData.primary300), onRatingUpdate: (rate) {}, ), const Divider(), const SizedBox(height: 5), - Text(review.comment ?? '', style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + review.comment ?? '', + style: TextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ], ), ), @@ -430,31 +789,71 @@ class OnDemandDetailsScreen extends StatelessWidget { ); } - Widget showTiming(BuildContext context, OnDemandDetailsController controller, bool isDark) { + Widget showTiming( + BuildContext context, + OnDemandDetailsController controller, + bool isDark, + ) { final provider = controller.provider; return Container( - decoration: BoxDecoration(color: isDark ? AppThemeData.grey300 : Colors.white, borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey300 : Colors.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - child: Text("Service Timing".tr(), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)), + child: Text( + "Service Timing".tr(), + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: AppThemeData.regular, + color: AppThemeData.primary300, + ), + ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row( children: [ - Expanded(child: _timeCard(context, "Start Time : ".tr(), provider.startTime.toString(), isDark)), + Expanded( + child: _timeCard( + context, + "Start Time : ".tr(), + provider.startTime.toString(), + isDark, + ), + ), const SizedBox(width: 10), - Expanded(child: _timeCard(context, "End Time : ".tr(), provider.endTime.toString(), isDark)), + Expanded( + child: _timeCard( + context, + "End Time : ".tr(), + provider.endTime.toString(), + isDark, + ), + ), ], ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - child: Text("Service Days".tr(), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)), + child: Text( + "Service Days".tr(), + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: AppThemeData.regular, + color: AppThemeData.primary300, + ), + ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -466,10 +865,30 @@ class OnDemandDetailsScreen extends StatelessWidget { .map( (day) => Card( elevation: 2, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6), side: BorderSide(color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1), width: 1)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + side: BorderSide( + color: + isDark + ? const Color(0XFF3c3a2e) + : const Color(0XFFC3C5D1), + width: 1, + ), + ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 20), - child: Text(day, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))), + padding: const EdgeInsets.symmetric( + vertical: 7, + horizontal: 20, + ), + child: Text( + day, + style: TextStyle( + color: + isDark + ? const Color(0XFFa5a292) + : const Color(0XFF5A5D6D), + ), + ), ), ), ) @@ -482,16 +901,39 @@ class OnDemandDetailsScreen extends StatelessWidget { ); } - Widget _timeCard(BuildContext context, String title, String value, bool isDark) { + Widget _timeCard( + BuildContext context, + String title, + String value, + bool isDark, + ) { return Card( elevation: 2, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6), side: BorderSide(color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1), width: 1)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + side: BorderSide( + color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1), + width: 1, + ), + ), child: Padding( padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 20), child: Row( children: [ - Text(title, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))), - Text(value, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))), + Text( + title, + style: TextStyle( + color: + isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D), + ), + ), + Text( + value, + style: TextStyle( + color: + isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D), + ), + ), ], ), ), diff --git a/lib/screen_ui/on_demand_service/on_demand_home_screen.dart b/lib/screen_ui/on_demand_service/on_demand_home_screen.dart index fbe5aa6..0fea656 100644 --- a/lib/screen_ui/on_demand_service/on_demand_home_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_home_screen.dart @@ -20,7 +20,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/on_demand_home_controller.dart'; import '../../models/category_model.dart'; import '../../models/provider_serivce_model.dart'; @@ -51,8 +51,20 @@ class OnDemandHomeScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: const BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: const Center(child: Padding(padding: EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: const Center( + child: Padding( + padding: EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -61,8 +73,23 @@ class OnDemandHomeScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Constant.userModel == null - ? InkWell(onTap: () => Get.offAll(const LoginScreen()), child: Text("Login".tr(), style: AppThemeData.boldTextStyle(color: AppThemeData.grey900, fontSize: 12))) - : Text(Constant.userModel!.fullName(), style: AppThemeData.boldTextStyle(color: AppThemeData.grey900, fontSize: 12)), + ? InkWell( + onTap: () => Get.offAll(const LoginScreen()), + child: Text( + "Login".tr(), + style: AppThemeData.boldTextStyle( + color: AppThemeData.grey900, + fontSize: 12, + ), + ), + ) + : Text( + Constant.userModel!.fullName(), + style: AppThemeData.boldTextStyle( + color: AppThemeData.grey900, + fontSize: 12, + ), + ), InkWell( onTap: () async { if (Constant.userModel != null) { @@ -76,10 +103,13 @@ class OnDemandHomeScreen extends StatelessWidget { } else { Constant.checkPermission( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); // ✅ declare it once here! - ShippingAddress shippingAddress = ShippingAddress(); + ShippingAddress shippingAddress = + ShippingAddress(); try { await Geolocator.requestPermission(); @@ -87,41 +117,72 @@ class OnDemandHomeScreen extends StatelessWidget { ShowToastDialog.closeLoader(); if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lat = + firstPlace.coordinates.latitude; + final lng = + firstPlace.coordinates.longitude; final address = firstPlace.address; shippingAddress.addressAs = "Home"; - shippingAddress.locality = address.toString(); - shippingAddress.location = UserLocation(latitude: lat, longitude: lng); - Constant.selectedLocation = shippingAddress; + shippingAddress.locality = + address.toString(); + shippingAddress.location = UserLocation( + latitude: lat, + longitude: lng, + ); + Constant.selectedLocation = + shippingAddress; controller.getData(); Get.back(); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); - shippingAddress.locality = "Picked from Map"; // You can reverse-geocode + shippingAddress + .location = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, + ); + shippingAddress.locality = + "Picked from Map"; // You can reverse-geocode - Constant.selectedLocation = shippingAddress; + Constant.selectedLocation = + shippingAddress; controller.getData(); } }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; - shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + shippingAddress.location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; - shippingAddress.locality = currentLocation; + shippingAddress.locality = + currentLocation; }); Constant.selectedLocation = shippingAddress; @@ -139,10 +200,21 @@ class OnDemandHomeScreen extends StatelessWidget { TextSpan( children: [ TextSpan( - text: Constant.selectedLocation.getFullAddress(), - style: TextStyle(fontFamily: AppThemeData.medium, overflow: TextOverflow.ellipsis, color: AppThemeData.grey900, fontSize: 14), + text: + Constant.selectedLocation + .getFullAddress(), + style: TextStyle( + fontFamily: AppThemeData.medium, + overflow: TextOverflow.ellipsis, + color: AppThemeData.grey900, + fontSize: 14, + ), + ), + WidgetSpan( + child: SvgPicture.asset( + "assets/icons/ic_down.svg", + ), ), - WidgetSpan(child: SvgPicture.asset("assets/icons/ic_down.svg")), ], ), ), @@ -157,7 +229,8 @@ class OnDemandHomeScreen extends StatelessWidget { body: controller.isLoading.value ? Constant.loader() - : Constant.isZoneAvailable == false || controller.providerList.isEmpty + : Constant.isZoneAvailable == false || + controller.providerList.isEmpty ? Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( @@ -166,12 +239,30 @@ class OnDemandHomeScreen extends StatelessWidget { children: [ Image.asset("assets/images/location.gif", height: 120), const SizedBox(height: 12), - Text("No Store Found in Your Area".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "No Store Found in Your Area".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "Currently, there are no available store in your zone. Try changing your location to find nearby options.".tr(), + "Currently, there are no available store in your zone. Try changing your location to find nearby options." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -188,7 +279,10 @@ class OnDemandHomeScreen extends StatelessWidget { ), ) : Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + padding: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 15, + ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -199,42 +293,95 @@ class OnDemandHomeScreen extends StatelessWidget { height: MediaQuery.of(context).size.height * 0.12, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark600 : AppThemeData.greyDark600, width: 1), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.greyDark600, + width: 1, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: controller.categories.isEmpty - ? Constant.showEmptyView(message: "No Categories".tr()) + ? Constant.showEmptyView( + message: "No Categories".tr(), + ) : Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: ListView.builder( - itemCount: controller.categories.length > 3 ? 3 : controller.categories.length, + itemCount: + controller.categories.length > + 3 + ? 3 + : controller + .categories + .length, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { - final category = controller.categories[index]; + final category = + controller + .categories[index]; return InkWell( onTap: () { - Get.to(() => ViewCategoryServiceListScreen(), arguments: {'categoryId': category.id, 'categoryTitle': category.title}); + Get.to( + () => + ViewCategoryServiceListScreen(), + arguments: { + 'categoryId': + category.id, + 'categoryTitle': + category.title, + }, + ); }, - child: CategoryView(category: category, index: index, isDark: isDark), + child: CategoryView( + category: category, + index: index, + isDark: isDark, + ), ); }, ), ), if (controller.categories.length > 3) Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ InkWell( onTap: () { - Get.to(() => const OnDemandCategoryScreen()); + Get.to( + () => + const OnDemandCategoryScreen(), + ); }, - child: ClipOval(child: Container(width: 50, height: 50, color: AppThemeData.grey200, child: const Center(child: Icon(Icons.chevron_right)))), + child: ClipOval( + child: Container( + width: 50, + height: 50, + color: + AppThemeData + .grey200, + child: const Center( + child: Icon( + Icons.chevron_right, + ), + ), + ), + ), ), const SizedBox(height: 5), SizedBox( @@ -242,9 +389,17 @@ class OnDemandHomeScreen extends StatelessWidget { child: Center( child: Text( "View All".tr(), - textAlign: TextAlign.center, + textAlign: + TextAlign.center, maxLines: 1, - style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), ), @@ -262,14 +417,28 @@ class OnDemandHomeScreen extends StatelessWidget { Expanded( child: Text( "Most Popular services".tr(), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w600), + style: TextStyle( + color: + isDark ? Colors.white : Colors.black, + fontSize: 18, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w600, + ), ), ), InkWell( onTap: () { Get.to(() => ViewAllPopularServiceScreen()); }, - child: Text("View all".tr(), style: TextStyle(color: AppThemeData.primary300, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w600)), + child: Text( + "View all".tr(), + style: TextStyle( + color: AppThemeData.primary300, + fontSize: 14, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w600, + ), + ), ), ], ), @@ -280,9 +449,16 @@ class OnDemandHomeScreen extends StatelessWidget { shrinkWrap: true, padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), - itemCount: controller.providerList.length >= 6 ? 6 : controller.providerList.length, + itemCount: + controller.providerList.length >= 6 + ? 6 + : controller.providerList.length, itemBuilder: (_, index) { - return ServiceView(provider: controller.providerList[index], controller: controller, isDark: isDark); + return ServiceView( + provider: controller.providerList[index], + controller: controller, + isDark: isDark, + ); }, ), ], @@ -334,7 +510,13 @@ class BannerView extends StatelessWidget { final banner = bannerList[index]; return ClipRRect( borderRadius: BorderRadius.circular(15), - child: SizedBox(width: MediaQuery.of(context).size.width * 0.8, child: NetworkImageWidget(imageUrl: banner.photo ?? '', fit: BoxFit.cover)), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + child: NetworkImageWidget( + imageUrl: banner.photo ?? '', + fit: BoxFit.cover, + ), + ), ); }, ), @@ -344,7 +526,18 @@ class BannerView extends StatelessWidget { return Row( children: List.generate(bannerList.length, (index) { bool isSelected = currentPage.value == index; - return Expanded(child: Container(height: 4, decoration: BoxDecoration(color: isSelected ? AppThemeData.grey300 : AppThemeData.grey100, borderRadius: BorderRadius.circular(5)))); + return Expanded( + child: Container( + height: 4, + decoration: BoxDecoration( + color: + isSelected + ? AppThemeData.grey300 + : AppThemeData.grey100, + borderRadius: BorderRadius.circular(5), + ), + ), + ); }), ); }), @@ -358,7 +551,12 @@ class CategoryView extends StatelessWidget { final int index; final bool isDark; - const CategoryView({super.key, required this.category, required this.index, required this.isDark}); + const CategoryView({ + super.key, + required this.category, + required this.index, + required this.isDark, + }); @override Widget build(BuildContext context) { @@ -370,11 +568,21 @@ class CategoryView extends StatelessWidget { Container( height: 55, width: 55, - decoration: BoxDecoration(color: Constant.colorList[index % Constant.colorList.length], borderRadius: BorderRadius.circular(50)), + decoration: BoxDecoration( + color: Constant.colorList[index % Constant.colorList.length], + borderRadius: BorderRadius.circular(50), + ), child: ClipOval( child: Padding( padding: const EdgeInsets.all(14.0), - child: CachedNetworkImage(imageUrl: category.image.toString(), errorWidget: (_, __, ___) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover)), + child: CachedNetworkImage( + imageUrl: category.image.toString(), + errorWidget: + (_, __, ___) => Image.network( + Constant.placeHolderImage, + fit: BoxFit.cover, + ), + ), ), ), ), @@ -382,7 +590,15 @@ class CategoryView extends StatelessWidget { SizedBox( width: 70, child: Center( - child: Text(category.title ?? "", textAlign: TextAlign.center, maxLines: 1, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + category.title ?? "", + textAlign: TextAlign.center, + maxLines: 1, + style: AppThemeData.semiBoldTextStyle( + color: + isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ), ), ], @@ -396,40 +612,70 @@ class ServiceView extends StatelessWidget { final bool isDark; final OnDemandHomeController? controller; - const ServiceView({super.key, required this.provider, this.isDark = false, this.controller}); + const ServiceView({ + super.key, + required this.provider, + this.isDark = false, + this.controller, + }); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { - Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': provider}); + Get.to( + () => OnDemandDetailsScreen(), + arguments: {'providerModel': provider}, + ); }, child: Container( margin: const EdgeInsets.symmetric(vertical: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade200), + border: Border.all( + color: isDark ? AppThemeData.grey500 : Colors.grey.shade200, + ), color: isDark ? AppThemeData.grey900 : Colors.white, ), child: Row( children: [ // --- Left Image --- ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), child: CachedNetworkImage( - imageUrl: provider.photos.isNotEmpty ? provider.photos[0] : Constant.placeHolderImage, + imageUrl: + provider.photos.isNotEmpty + ? provider.photos[0] + : Constant.placeHolderImage, width: 110, height: MediaQuery.of(context).size.height * 0.16, fit: BoxFit.cover, - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: AlwaysStoppedAnimation( + AppThemeData.primary300, + ), + ), + ), + errorWidget: + (context, url, error) => Image.network( + Constant.placeHolderImage, + fit: BoxFit.cover, + ), ), ), // --- Right Content --- Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 10, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -442,17 +688,40 @@ class ServiceView extends StatelessWidget { provider.title ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black, + ), ), ), if (controller != null) Obx( () => GestureDetector( - onTap: () => controller!.toggleFavourite(provider), + onTap: + () => controller!.toggleFavourite(provider), child: Icon( - controller!.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? Icons.favorite : Icons.favorite_border, + controller!.lstFav + .where( + (element) => + element.service_id == provider.id, + ) + .isNotEmpty + ? Icons.favorite + : Icons.favorite_border, size: 24, - color: controller!.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? AppThemeData.primary300 : (isDark ? Colors.white38 : Colors.black38), + color: + controller!.lstFav + .where( + (element) => + element.service_id == + provider.id, + ) + .isNotEmpty + ? AppThemeData.primary300 + : (isDark + ? Colors.white38 + : Colors.black38), ), ), ), @@ -464,10 +733,18 @@ class ServiceView extends StatelessWidget { // Category if (controller != null) FutureBuilder( - future: controller!.getCategory(provider.categoryId ?? ""), + future: controller!.getCategory( + provider.categoryId ?? "", + ), builder: (ctx, snap) { if (!snap.hasData) return const SizedBox.shrink(); - return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 13, color: isDark ? Colors.white70 : Colors.black54)); + return Text( + snap.data?.title ?? "", + style: TextStyle( + fontSize: 13, + color: isDark ? Colors.white70 : Colors.black54, + ), + ); }, ), @@ -493,21 +770,39 @@ class ServiceView extends StatelessWidget { Widget _buildPrice() { if (provider.disPrice == "" || provider.disPrice == "0") { return Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.price) + : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : AppThemeData.primary300, + ), ); } else { return Row( children: [ Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.disPrice ?? '0') + : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : AppThemeData.primary300, + ), ), const SizedBox(width: 6), Flexible( child: Text( - provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/hr', - style: const TextStyle(fontSize: 12, color: Colors.grey, decoration: TextDecoration.lineThrough), + provider.priceUnit == 'Fixed' + ? Constant.amountShow(amount: provider.price) + : '${Constant.amountShow(amount: provider.price ?? "0")}/hr', + style: const TextStyle( + fontSize: 12, + color: Colors.grey, + decoration: TextDecoration.lineThrough, + ), overflow: TextOverflow.ellipsis, ), ), @@ -522,11 +817,21 @@ class ServiceView extends StatelessWidget { rating = (provider.reviewsSum ?? 0) / (provider.reviewsCount ?? 1); } return Container( - decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(12)), + decoration: BoxDecoration( + color: AppThemeData.warning400, + borderRadius: BorderRadius.circular(12), + ), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Row( mainAxisSize: MainAxisSize.min, - children: [const Icon(Icons.star, size: 14, color: Colors.white), const SizedBox(width: 3), Text(rating.toStringAsFixed(1), style: const TextStyle(fontSize: 12, color: Colors.white))], + children: [ + const Icon(Icons.star, size: 14, color: Colors.white), + const SizedBox(width: 3), + Text( + rating.toStringAsFixed(1), + style: const TextStyle(fontSize: 12, color: Colors.white), + ), + ], ), ); } diff --git a/lib/screen_ui/on_demand_service/on_demand_order_details_screen.dart b/lib/screen_ui/on_demand_service/on_demand_order_details_screen.dart index 95c1555..9db13d4 100644 --- a/lib/screen_ui/on_demand_service/on_demand_order_details_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_order_details_screen.dart @@ -2,7 +2,7 @@ import 'package:clipboard/clipboard.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import '../../controllers/on_demand_order_details_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -38,12 +38,30 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Order Details".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Order Details".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -56,63 +74,147 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (controller.onProviderOrder.value?.status ?? '') == Constant.orderCancelled + (controller.onProviderOrder.value?.status ?? '') == + Constant.orderCancelled ? Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Padding( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + padding: EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Cancel Reason'.tr(), style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(controller.onProviderOrder.value?.reason ?? '', style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.danger300)), + Text( + 'Cancel Reason'.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + controller + .onProviderOrder + .value + ?.reason ?? + '', + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.danger300, + ), + ), ], ), ), ) : Container(), - (controller.onProviderOrder.value?.status ?? '') == Constant.orderCancelled ? SizedBox(height: 10) : SizedBox.shrink(), + (controller.onProviderOrder.value?.status ?? '') == + Constant.orderCancelled + ? SizedBox(height: 10) + : SizedBox.shrink(), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Padding( - padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10), + padding: EdgeInsets.symmetric( + vertical: 15, + horizontal: 10, + ), child: Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text('Booking ID'.tr(), style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + 'Booking ID'.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), InkWell( onTap: () { - FlutterClipboard.copy(controller.onProviderOrder.value?.id ?? '').then((value) { + FlutterClipboard.copy( + controller + .onProviderOrder + .value + ?.id ?? + '', + ).then((value) { SnackBar snackBar = SnackBar( content: Text( "Booking ID Copied".tr(), textAlign: TextAlign.center, - style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), backgroundColor: Colors.black38, ); - ScaffoldMessenger.of(context).showSnackBar(snackBar); + ScaffoldMessenger.of( + context, + ).showSnackBar(snackBar); }); }, - child: Text('# ${controller.onProviderOrder.value?.id ?? ''}', style: AppThemeData.mediumTextStyle(fontSize: 15, color: AppThemeData.primary300)), + child: Text( + '# ${controller.onProviderOrder.value?.id ?? ''}', + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: AppThemeData.primary300, + ), + ), ), ], ), SizedBox(height: 10), Text( "${'Booking Address :'.tr()} ${controller.onProviderOrder.value?.address?.getFullAddress()}", - style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -122,8 +224,16 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Row( children: [ @@ -136,8 +246,20 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { borderRadius: BorderRadius.circular(10), image: DecorationImage( image: NetworkImage( - (controller.onProviderOrder.value != null && controller.onProviderOrder.value!.provider.photos.isNotEmpty) - ? controller.onProviderOrder.value!.provider.photos.first + (controller.onProviderOrder.value != + null && + controller + .onProviderOrder + .value! + .provider + .photos + .isNotEmpty) + ? controller + .onProviderOrder + .value! + .provider + .photos + .first : Constant.placeHolderImage, ), fit: BoxFit.cover, @@ -152,23 +274,71 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 6), child: Text( - controller.onProviderOrder.value?.provider.title ?? "", - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller + .onProviderOrder + .value + ?.provider + .title ?? + "", + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), Row( children: [ Padding( - padding: const EdgeInsets.only(top: 6), - child: Text('${'Date:'.tr()} ', style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + padding: const EdgeInsets.only( + top: 6, + ), + child: Text( + '${'Date:'.tr()} ', + style: + AppThemeData.regularTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), ), Padding( - padding: const EdgeInsets.only(top: 6), + padding: const EdgeInsets.only( + top: 6, + ), child: Text( - controller.onProviderOrder.value?.scheduleDateTime != null - ? DateFormat('dd-MMM-yyyy').format(controller.onProviderOrder.value!.scheduleDateTime!.toDate()) + controller + .onProviderOrder + .value + ?.scheduleDateTime != + null + ? DateFormat( + 'dd-MMM-yyyy', + ).format( + controller + .onProviderOrder + .value! + .scheduleDateTime! + .toDate(), + ) : "", - style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.regularTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), ], @@ -176,16 +346,51 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Row( children: [ Padding( - padding: const EdgeInsets.only(top: 6), - child: Text('${'Time:'.tr()} ', style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + padding: const EdgeInsets.only( + top: 6, + ), + child: Text( + '${'Time:'.tr()} ', + style: + AppThemeData.regularTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), ), Padding( - padding: const EdgeInsets.only(top: 6), + padding: const EdgeInsets.only( + top: 6, + ), child: Text( - controller.onProviderOrder.value?.scheduleDateTime != null - ? DateFormat('hh:mm a').format(controller.onProviderOrder.value!.scheduleDateTime!.toDate()) + controller + .onProviderOrder + .value + ?.scheduleDateTime != + null + ? DateFormat('hh:mm a').format( + controller + .onProviderOrder + .value! + .scheduleDateTime! + .toDate(), + ) : "", - style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.regularTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), ], @@ -196,23 +401,50 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ], ), ), - (controller.onProviderOrder.value?.status == Constant.orderAccepted || - controller.onProviderOrder.value?.status == Constant.orderAssigned || - controller.onProviderOrder.value?.status == Constant.orderOngoing || - controller.onProviderOrder.value?.status == Constant.orderCompleted) && - (controller.onProviderOrder.value?.workerId != null && controller.onProviderOrder.value!.workerId!.isNotEmpty) + (controller.onProviderOrder.value?.status == + Constant.orderAccepted || + controller.onProviderOrder.value?.status == + Constant.orderAssigned || + controller.onProviderOrder.value?.status == + Constant.orderOngoing || + controller.onProviderOrder.value?.status == + Constant.orderCompleted) && + (controller.onProviderOrder.value?.workerId != + null && + controller + .onProviderOrder + .value! + .workerId! + .isNotEmpty) ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(vertical: 10), - child: Text('About Worker'.tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + 'About Worker'.tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -226,35 +458,99 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { CircleAvatar( radius: 30, backgroundImage: NetworkImage( - controller.worker.value?.profilePictureURL.isNotEmpty == true ? controller.worker.value!.profilePictureURL : Constant.placeHolderImage, + controller + .worker + .value + ?.profilePictureURL + .isNotEmpty == + true + ? controller + .worker + .value! + .profilePictureURL + : Constant + .placeHolderImage, ), ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - controller.worker.value?.fullName() ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.bold), + controller + .worker + .value + ?.fullName() ?? + '', + style: TextStyle( + color: + isDark + ? Colors + .white + : Colors + .black, + fontFamily: + AppThemeData + .regular, + fontSize: 14, + fontWeight: + FontWeight.bold, + ), + ), + const SizedBox( + height: 5, ), - const SizedBox(height: 5), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Padding( - padding: const EdgeInsets.only(top: 3), - child: Icon(Icons.location_on_outlined, size: 15, color: isDark ? Colors.white : Colors.black), + padding: + const EdgeInsets.only( + top: 3, + ), + child: Icon( + Icons + .location_on_outlined, + size: 15, + color: + isDark + ? Colors + .white + : Colors + .black, + ), ), Expanded( child: Text( - controller.worker.value?.address ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14), + controller + .worker + .value + ?.address ?? + '', + style: TextStyle( + color: + isDark + ? Colors + .white + : Colors + .black, + fontFamily: + AppThemeData + .regular, + fontSize: 14, + ), ), ), ], ), - const SizedBox(height: 10), + const SizedBox( + height: 10, + ), ], ), ), @@ -264,19 +560,61 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { SizedBox(width: 10), // Rating Box Container( - decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)), - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: AppThemeData.warning400, + borderRadius: + BorderRadius.circular(16), + ), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, size: 16, color: Colors.white), + const Icon( + Icons.star, + size: 16, + color: Colors.white, + ), const SizedBox(width: 3), Text( - (controller.worker.value != null && double.parse(controller.worker.value!.reviewsCount.toString()) != 0) - ? (double.parse(controller.worker.value!.reviewsSum.toString()) / double.parse(controller.worker.value!.reviewsCount.toString())) + (controller.worker.value != + null && + double.parse( + controller + .worker + .value! + .reviewsCount + .toString(), + ) != + 0) + ? (double.parse( + controller + .worker + .value! + .reviewsSum + .toString(), + ) / + double.parse( + controller + .worker + .value! + .reviewsCount + .toString(), + )) .toStringAsFixed(1) : '0', - style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white), + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 12, + fontFamily: + AppThemeData.regular, + fontWeight: + FontWeight.w500, + color: Colors.white, + ), ), ], ), @@ -284,17 +622,40 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ], ), Visibility( - visible: controller.onProviderOrder.value?.status == Constant.orderCompleted ? true : false, + visible: + controller + .onProviderOrder + .value + ?.status == + Constant.orderCompleted + ? true + : false, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: SizedBox( - width: MediaQuery.of(context).size.width, + width: + MediaQuery.of( + context, + ).size.width, child: ElevatedButton( // onPressed: () async { // Get.to(() => OnDemandReviewScreen(), arguments: {'order': controller.onProviderOrder.value, 'reviewFor': "Worker"}); // }, onPressed: () async { - final result = await Get.to(() => OnDemandReviewScreen(), arguments: {'order': controller.onProviderOrder.value, 'reviewFor': "Worker"}); + final result = await Get.to( + () => + OnDemandReviewScreen(), + arguments: { + 'order': + controller + .onProviderOrder + .value, + 'reviewFor': "Worker", + }, + ); // If review was submitted successfully if (result == true) { @@ -302,33 +663,105 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { } }, - style: ElevatedButton.styleFrom(backgroundColor: Colors.orange, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), - child: Text('Add Review'.tr(), style: AppThemeData.regularTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + style: ElevatedButton.styleFrom( + backgroundColor: + Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), + ), + child: Text( + 'Add Review'.tr(), + style: + AppThemeData.regularTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + ), ), ), ), ), - controller.onProviderOrder.value?.status == Constant.orderAccepted || - controller.onProviderOrder.value?.status == Constant.orderOngoing || - controller.onProviderOrder.value?.status == Constant.orderAssigned + controller + .onProviderOrder + .value + ?.status == + Constant.orderAccepted || + controller + .onProviderOrder + .value + ?.status == + Constant.orderOngoing || + controller + .onProviderOrder + .value + ?.status == + Constant.orderAssigned ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, children: [ Expanded( child: ElevatedButton( onPressed: () async { - Constant.makePhoneCall(controller.worker.value!.phoneNumber.toString()); + Constant.makePhoneCall( + controller + .worker + .value! + .phoneNumber + .toString(), + ); }, - style: ElevatedButton.styleFrom(backgroundColor: Color(0xFFFF6839), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFFFF6839, + ), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, children: [ - Icon(Icons.call, color: AppThemeData.grey50), + Icon( + Icons.call, + color: + AppThemeData + .grey50, + ), SizedBox(width: 10), - Text('Call'.tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.grey50)), + Text( + 'Call'.tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData + .grey50, + ), + ), ], ), ), @@ -337,32 +770,88 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Expanded( child: ElevatedButton( onPressed: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": Constant.userModel?.fullName(), - "restaurantName": "${controller.worker.value?.firstName ?? ''} ${controller.worker.value?.lastName ?? ''}", - "orderId": controller.onProviderOrder.value?.id, - "restaurantId": controller.worker.value?.id, - "customerId": Constant.userModel?.id, - "customerProfileImage": Constant.userModel?.profilePictureURL, - "restaurantProfileImage": controller.worker.value?.profilePictureURL, - "token": controller.worker.value?.fcmToken, - "chatType": 'worker', + "customerName": + Constant + .userModel + ?.fullName(), + "restaurantName": + "${controller.worker.value?.firstName ?? ''} ${controller.worker.value?.lastName ?? ''}", + "orderId": + controller + .onProviderOrder + .value + ?.id, + "restaurantId": + controller + .worker + .value + ?.id, + "customerId": + Constant + .userModel + ?.id, + "customerProfileImage": + Constant + .userModel + ?.profilePictureURL, + "restaurantProfileImage": + controller + .worker + .value + ?.profilePictureURL, + "token": + controller + .worker + .value + ?.fcmToken, + "chatType": + 'worker', }, ); }, - style: ElevatedButton.styleFrom(backgroundColor: AppThemeData.primary300, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + style: ElevatedButton.styleFrom( + backgroundColor: + AppThemeData + .primary300, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, children: [ - Icon(Icons.chat_bubble, color: AppThemeData.grey50), + Icon( + Icons.chat_bubble, + color: + AppThemeData + .grey50, + ), SizedBox(width: 10), - Text('Chat'.tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.grey50)), + Text( + 'Chat'.tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData + .grey50, + ), + ), ], ), ), @@ -380,13 +869,30 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { : SizedBox(), Padding( padding: EdgeInsets.symmetric(vertical: 10), - child: Text("About provider".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + "About provider".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -400,22 +906,56 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { CircleAvatar( radius: 30, backgroundImage: NetworkImage( - controller.providerUser.value?.profilePictureURL?.isNotEmpty == true ? controller.providerUser.value!.profilePictureURL! : Constant.placeHolderImage, + controller + .providerUser + .value + ?.profilePictureURL + ?.isNotEmpty == + true + ? controller + .providerUser + .value! + .profilePictureURL! + : Constant.placeHolderImage, ), ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.providerUser.value?.fullName() ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.bold), + controller.providerUser.value + ?.fullName() ?? + '', + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: + AppThemeData.regular, + fontSize: 14, + fontWeight: FontWeight.bold, + ), ), const SizedBox(height: 5), Text( - controller.providerUser.value?.email ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14), + controller + .providerUser + .value + ?.email ?? + '', + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: + AppThemeData.regular, + fontSize: 14, + ), ), const SizedBox(height: 10), ], @@ -426,19 +966,57 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ), // Rating Box Container( - decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)), - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: AppThemeData.warning400, + borderRadius: BorderRadius.circular(16), + ), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, size: 16, color: Colors.white), + const Icon( + Icons.star, + size: 16, + color: Colors.white, + ), const SizedBox(width: 3), Text( - (controller.providerUser.value != null && double.parse(controller.providerUser.value!.reviewsCount.toString()) != 0) - ? (double.parse(controller.providerUser.value!.reviewsSum.toString()) / double.parse(controller.providerUser.value!.reviewsCount.toString())) + (controller.providerUser.value != + null && + double.parse( + controller + .providerUser + .value! + .reviewsCount + .toString(), + ) != + 0) + ? (double.parse( + controller + .providerUser + .value! + .reviewsSum + .toString(), + ) / + double.parse( + controller + .providerUser + .value! + .reviewsCount + .toString(), + )) .toStringAsFixed(1) : '0', - style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white), + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 12, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + color: Colors.white, + ), ), ], ), @@ -446,86 +1024,251 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ], ), Visibility( - visible: controller.onProviderOrder.value?.status == Constant.orderCompleted ? true : false, + visible: + controller + .onProviderOrder + .value + ?.status == + Constant.orderCompleted + ? true + : false, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: SizedBox( width: MediaQuery.of(context).size.width, child: ElevatedButton( onPressed: () async { - final result = await Get.to(() => OnDemandReviewScreen(), arguments: {'order': controller.onProviderOrder.value, 'reviewFor': "Provider"}); + final result = await Get.to( + () => OnDemandReviewScreen(), + arguments: { + 'order': + controller + .onProviderOrder + .value, + 'reviewFor': "Provider", + }, + ); if (result == true) { await controller.getData(); } }, - style: ElevatedButton.styleFrom(backgroundColor: Colors.orange, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), - child: Text('Add Review'.tr(), style: AppThemeData.regularTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 16, + ), + ), + ), + child: Text( + 'Add Review'.tr(), + style: AppThemeData.regularTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), ), ), ), - controller.onProviderOrder.value?.status == Constant.orderAccepted || - controller.onProviderOrder.value?.status == Constant.orderOngoing || - controller.onProviderOrder.value?.status == Constant.orderAssigned + controller.onProviderOrder.value?.status == + Constant.orderAccepted || + controller + .onProviderOrder + .value + ?.status == + Constant.orderOngoing || + controller + .onProviderOrder + .value + ?.status == + Constant.orderAssigned ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: ElevatedButton( onPressed: () async { - Constant.makePhoneCall(controller.providerUser.value!.phoneNumber.toString()); + Constant.makePhoneCall( + controller + .providerUser + .value! + .phoneNumber + .toString(), + ); }, - style: ElevatedButton.styleFrom(backgroundColor: Color(0xFFFF6839), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFFFF6839, + ), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(16), + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Icon(Icons.call, color: AppThemeData.grey50), + Icon( + Icons.call, + color: AppThemeData.grey50, + ), SizedBox(width: 10), - Text('Call'.tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.grey50)), + Text( + 'Call'.tr(), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData + .grey50, + ), + ), ], ), ), ), - if ((Constant.isSubscriptionModelApplied == false && Constant.sectionConstantModel?.adminCommision?.isEnabled == false) || - ((Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel?.adminCommision?.isEnabled == true) && - controller.onProviderOrder.value?.provider.subscriptionPlan?.features?.chat == true)) + if ((Constant.isSubscriptionModelApplied == + false && + Constant + .sectionConstantModel + ?.adminCommision + ?.isEnabled == + false) || + ((Constant.isSubscriptionModelApplied == + true || + Constant + .sectionConstantModel + ?.adminCommision + ?.isEnabled == + true) && + controller + .onProviderOrder + .value + ?.provider + .subscriptionPlan + ?.features + ?.chat == + true)) const SizedBox(width: 10), - if ((Constant.isSubscriptionModelApplied == false && Constant.sectionConstantModel?.adminCommision?.isEnabled == false) || - ((Constant.isSubscriptionModelApplied == true || Constant.sectionConstantModel?.adminCommision?.isEnabled == true) && - controller.onProviderOrder.value?.provider.subscriptionPlan?.features?.chat == true)) + if ((Constant.isSubscriptionModelApplied == + false && + Constant + .sectionConstantModel + ?.adminCommision + ?.isEnabled == + false) || + ((Constant.isSubscriptionModelApplied == + true || + Constant + .sectionConstantModel + ?.adminCommision + ?.isEnabled == + true) && + controller + .onProviderOrder + .value + ?.provider + .subscriptionPlan + ?.features + ?.chat == + true)) Expanded( child: ElevatedButton( onPressed: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": Constant.userModel?.fullName(), - "restaurantName": "${controller.providerUser.value?.firstName ?? ''} ${controller.providerUser.value?.lastName ?? ''}", - "orderId": controller.onProviderOrder.value?.id, - "restaurantId": controller.providerUser.value?.id, - "customerId": Constant.userModel?.id, - "customerProfileImage": Constant.userModel?.profilePictureURL, - "restaurantProfileImage": controller.providerUser.value?.profilePictureURL, - "token": controller.providerUser.value?.fcmToken, + "customerName": + Constant.userModel + ?.fullName(), + "restaurantName": + "${controller.providerUser.value?.firstName ?? ''} ${controller.providerUser.value?.lastName ?? ''}", + "orderId": + controller + .onProviderOrder + .value + ?.id, + "restaurantId": + controller + .providerUser + .value + ?.id, + "customerId": + Constant + .userModel + ?.id, + "customerProfileImage": + Constant + .userModel + ?.profilePictureURL, + "restaurantProfileImage": + controller + .providerUser + .value + ?.profilePictureURL, + "token": + controller + .providerUser + .value + ?.fcmToken, "chatType": 'Provider', }, ); }, - style: ElevatedButton.styleFrom(backgroundColor: AppThemeData.primary300, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))), + style: ElevatedButton.styleFrom( + backgroundColor: + AppThemeData.primary300, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 16, + ), + ), + ), child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Icon(Icons.chat_bubble, color: AppThemeData.grey50), + Icon( + Icons.chat_bubble, + color: + AppThemeData.grey50, + ), SizedBox(width: 10), - Text('Chat'.tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: AppThemeData.grey50)), + Text( + 'Chat'.tr(), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + AppThemeData + .grey50, + ), + ), ], ), ), @@ -538,14 +1281,31 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ), ), ), - (controller.onProviderOrder.value?.status != Constant.orderCompleted || controller.onProviderOrder.value?.status != Constant.orderCancelled) && - controller.onProviderOrder.value?.provider.priceUnit == "Fixed" + (controller.onProviderOrder.value?.status != + Constant.orderCompleted || + controller.onProviderOrder.value?.status != + Constant.orderCancelled) && + controller + .onProviderOrder + .value + ?.provider + .priceUnit == + "Fixed" ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(vertical: 10), - child: Text("Price Detail".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + "Price Detail".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), priceTotalRow(controller, isDark), ], @@ -553,18 +1313,44 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - controller.onProviderOrder.value?.paymentStatus == false || controller.onProviderOrder.value?.extraPaymentStatus == false + controller + .onProviderOrder + .value + ?.paymentStatus == + false || + controller + .onProviderOrder + .value + ?.extraPaymentStatus == + false ? Column( children: [ controller.couponList.isNotEmpty ? SizedBox( height: 85, child: ListView.builder( - itemCount: controller.couponList.length, - scrollDirection: Axis.horizontal, + itemCount: + controller + .couponList + .length, + scrollDirection: + Axis.horizontal, itemBuilder: (context, index) { - final coupon = controller.couponList[index]; - return GestureDetector(onTap: () => controller.applyCoupon(coupon), child: buildOfferItem(controller, index, isDark)); + final coupon = + controller + .couponList[index]; + return GestureDetector( + onTap: + () => controller + .applyCoupon( + coupon, + ), + child: buildOfferItem( + controller, + index, + isDark, + ), + ); }, ), ) @@ -575,46 +1361,112 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { : Offstage(), Padding( padding: EdgeInsets.symmetric(vertical: 16), - child: Text("Price Detail".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + child: Text( + "Price Detail".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), ), priceTotalRow(controller, isDark), ], ), - controller.onProviderOrder.value?.extraCharges.toString() != "" + controller.onProviderOrder.value?.extraCharges + .toString() != + "" ? Container( margin: EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Container( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 10), + padding: EdgeInsets.symmetric( + vertical: 8, + horizontal: 10, + ), child: Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text("Total Extra Charges : ".tr(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500)), Text( - Constant.amountShow(amount: controller.onProviderOrder.value?.extraCharges.toString()), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + "Total Extra Charges : ".tr(), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), + ), + Text( + Constant.amountShow( + amount: + controller + .onProviderOrder + .value + ?.extraCharges + .toString(), + ), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), ], ), SizedBox(height: 5), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( "Extra charge Notes : ".tr(), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), ), Text( - controller.onProviderOrder.value?.extraChargesDescription ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + controller + .onProviderOrder + .value + ?.extraChargesDescription ?? + '', + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), ], ), @@ -625,39 +1477,101 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { : SizedBox(), SizedBox(height: 10), Visibility( - visible: controller.onProviderOrder.value?.status == Constant.orderPlaced || controller.onProviderOrder.value?.newScheduleDateTime != null ? true : false, + visible: + controller.onProviderOrder.value?.status == + Constant.orderPlaced || + controller + .onProviderOrder + .value + ?.newScheduleDateTime != + null + ? true + : false, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey100, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, ), child: Padding( - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10), + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), child: Column( children: [ - controller.onProviderOrder.value?.newScheduleDateTime != null + controller + .onProviderOrder + .value + ?.newScheduleDateTime != + null ? Row( children: [ - Text("New Date : ".tr(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500)), Text( - DateFormat('dd-MMM-yyyy hh:mm a').format(controller.onProviderOrder.value!.newScheduleDateTime!.toDate()), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500), + "New Date : ".tr(), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: + AppThemeData.regular, + fontWeight: FontWeight.w500, + ), + ), + Text( + DateFormat( + 'dd-MMM-yyyy hh:mm a', + ).format( + controller + .onProviderOrder + .value! + .newScheduleDateTime! + .toDate(), + ), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black, + fontFamily: + AppThemeData.regular, + fontWeight: FontWeight.w500, + ), ), ], ) : SizedBox(), - controller.onProviderOrder.value?.status == Constant.orderPlaced || controller.onProviderOrder.value?.status == Constant.orderAccepted + controller.onProviderOrder.value?.status == + Constant.orderPlaced || + controller + .onProviderOrder + .value + ?.status == + Constant.orderAccepted ? Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: RoundedButtonFill( title: "Cancel Booking".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () { - showCancelBookingDialog(controller, isDark); + showCancelBookingDialog( + controller, + isDark, + ); }, ), ) @@ -669,7 +1583,10 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ), ), const SizedBox(height: 20), - controller.onProviderOrder.value?.extraPaymentStatus == false && controller.onProviderOrder.value?.status == Constant.orderOngoing + controller.onProviderOrder.value?.extraPaymentStatus == + false && + controller.onProviderOrder.value?.status == + Constant.orderOngoing ? Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: RoundedButtonFill( @@ -678,17 +1595,43 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { textColor: AppThemeData.grey50, onPress: () async { double finalTotalAmount = 0.0; - finalTotalAmount = double.parse(controller.onProviderOrder.value!.extraCharges.toString()); - Get.to(() => OnDemandPaymentScreen(), arguments: {'onDemandOrderModel': controller.onProviderOrder, 'totalAmount': finalTotalAmount, 'isExtra': true}); + finalTotalAmount = double.parse( + controller + .onProviderOrder + .value! + .extraCharges + .toString(), + ); + Get.to( + () => OnDemandPaymentScreen(), + arguments: { + 'onDemandOrderModel': + controller.onProviderOrder, + 'totalAmount': finalTotalAmount, + 'isExtra': true, + }, + ); }, ), ) : SizedBox(), - controller.onProviderOrder.value?.provider.priceUnit != "Fixed" && controller.onProviderOrder.value?.paymentStatus == false + controller.onProviderOrder.value?.provider.priceUnit != + "Fixed" && + controller + .onProviderOrder + .value + ?.paymentStatus == + false ? Visibility( - visible: controller.onProviderOrder.value?.status == Constant.orderOngoing ? true : false, + visible: + controller.onProviderOrder.value?.status == + Constant.orderOngoing + ? true + : false, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: RoundedButtonFill( title: 'Pay Now'.tr(), color: AppThemeData.primary300, @@ -697,13 +1640,46 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { double finalTotalAmount = 0.0; finalTotalAmount = controller.totalAmount.value + - double.parse(controller.onProviderOrder.value!.extraCharges!.isNotEmpty ? controller.onProviderOrder.value!.extraCharges.toString() : "0.0"); - controller.onProviderOrder.value?.discount = controller.discountAmount.toString(); - controller.onProviderOrder.value?.discountType = controller.discountType.toString(); - controller.onProviderOrder.value?.discountLabel = controller.discountLabel.toString(); - controller.onProviderOrder.value?.couponCode = controller.offerCode.toString(); + double.parse( + controller + .onProviderOrder + .value! + .extraCharges! + .isNotEmpty + ? controller + .onProviderOrder + .value! + .extraCharges + .toString() + : "0.0", + ); + controller.onProviderOrder.value?.discount = + controller.discountAmount.toString(); + controller + .onProviderOrder + .value + ?.discountType = + controller.discountType.toString(); + controller + .onProviderOrder + .value + ?.discountLabel = + controller.discountLabel.toString(); + controller + .onProviderOrder + .value + ?.couponCode = + controller.offerCode.toString(); - Get.to(() => OnDemandPaymentScreen(), arguments: {'onDemandOrderModel': controller.onProviderOrder, 'totalAmount': finalTotalAmount, 'isExtra': false}); + Get.to( + () => OnDemandPaymentScreen(), + arguments: { + 'onDemandOrderModel': + controller.onProviderOrder, + 'totalAmount': finalTotalAmount, + 'isExtra': false, + }, + ); }, ), ), @@ -717,7 +1693,11 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ); } - Widget buildOfferItem(OnDemandOrderDetailsController controller, int index, bool isDark) { + Widget buildOfferItem( + OnDemandOrderDetailsController controller, + int index, + bool isDark, + ) { return Obx(() { final coupon = controller.couponList[index]; @@ -725,7 +1705,11 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { margin: const EdgeInsets.fromLTRB(7, 10, 7, 10), height: 85, child: DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(10), + color: AppThemeData.primary300, + ), child: Padding( padding: const EdgeInsets.fromLTRB(12, 5, 12, 0), child: Column( @@ -734,13 +1718,26 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Image(image: AssetImage('assets/images/offer_icon.png'), height: 25, width: 25), + const Image( + image: AssetImage('assets/images/offer_icon.png'), + height: 25, + width: 25, + ), const SizedBox(width: 10), Container( margin: const EdgeInsets.only(top: 3), child: Text( - coupon.discountType == "Fix Price" ? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}" : "${coupon.discount} ${'% Off'.tr()}", - style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 0.7, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + coupon.discountType == "Fix Price" + ? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}" + : "${coupon.discount} ${'% Off'.tr()}", + style: TextStyle( + fontWeight: FontWeight.bold, + letterSpacing: 0.7, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), ], @@ -749,11 +1746,36 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(coupon.code ?? '', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, letterSpacing: 0.5, color: Colors.orange)), - Container(margin: const EdgeInsets.only(left: 15, right: 15, top: 3), width: 1, color: AppThemeData.grey50), Text( - "valid till ".tr() + controller.getDate(coupon.expiresAt!.toDate().toString()), - style: TextStyle(letterSpacing: 0.5, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + coupon.code ?? '', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + letterSpacing: 0.5, + color: Colors.orange, + ), + ), + Container( + margin: const EdgeInsets.only( + left: 15, + right: 15, + top: 3, + ), + width: 1, + color: AppThemeData.grey50, + ), + Text( + "valid till ".tr() + + controller.getDate( + coupon.expiresAt!.toDate().toString(), + ), + style: TextStyle( + letterSpacing: 0.5, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -765,13 +1787,19 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { }); } - Widget buildPromoCode(OnDemandOrderDetailsController controller, bool isDark) { + Widget buildPromoCode( + OnDemandOrderDetailsController controller, + bool isDark, + ) { return GestureDetector( child: Container( margin: const EdgeInsets.only(top: 10, bottom: 13), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, width: 0.3), + border: Border.all( + color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + width: 0.3, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), child: Padding( @@ -782,17 +1810,37 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { Expanded( child: Row( children: [ - Image.asset("assets/images/reedem.png", height: 50, width: 50), + Image.asset( + "assets/images/reedem.png", + height: 50, + width: 50, + ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Promo Code".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), overflow: TextOverflow.ellipsis), + Text( + "Promo Code".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + overflow: TextOverflow.ellipsis, + ), const SizedBox(height: 5), Text( "Apply promo code".tr(), - style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), overflow: TextOverflow.ellipsis, ), ], @@ -803,7 +1851,13 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ), FloatingActionButton( onPressed: () { - Get.bottomSheet(promoCodeSheet(controller, isDark), isScrollControlled: true, isDismissible: true, backgroundColor: Colors.transparent, enableDrag: true); + Get.bottomSheet( + promoCodeSheet(controller, isDark), + isScrollControlled: true, + isDismissible: true, + backgroundColor: Colors.transparent, + enableDrag: true, + ); }, mini: true, backgroundColor: Colors.blueGrey.shade50, @@ -817,11 +1871,17 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ); } - Widget promoCodeSheet(OnDemandOrderDetailsController controller, bool isDark) { + Widget promoCodeSheet( + OnDemandOrderDetailsController controller, + bool isDark, + ) { return Container( padding: EdgeInsets.only(bottom: Get.height / 4.3, left: 25, right: 25), height: Get.height * 0.88, - decoration: BoxDecoration(color: Colors.transparent, border: Border.all(style: BorderStyle.none)), + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(style: BorderStyle.none), + ), child: Column( children: [ InkWell( @@ -829,50 +1889,114 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { child: Container( height: 45, decoration: BoxDecoration( - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, width: 0.3), + border: Border.all( + color: + isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + width: 0.3, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, shape: BoxShape.circle, ), - child: Center(child: Icon(Icons.close, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, size: 28)), + child: Center( + child: Icon( + Icons.close, + color: + isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + size: 28, + ), + ), ), ), const SizedBox(height: 25), Expanded( child: Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + ), alignment: Alignment.center, child: SingleChildScrollView( child: Column( children: [ - Container(padding: const EdgeInsets.only(top: 30), child: const Image(image: AssetImage('assets/images/redeem_coupon.png'), width: 100)), Container( - padding: const EdgeInsets.only(top: 20), - child: Text('Redeem Your Coupons'.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)), - ), - Center( - child: Container( - padding: const EdgeInsets.only(top: 10, left: 22, right: 22), - child: Text("Voucher or Coupon code".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + padding: const EdgeInsets.only(top: 30), + child: const Image( + image: AssetImage('assets/images/redeem_coupon.png'), + width: 100, ), ), Container( - padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + padding: const EdgeInsets.only(top: 20), + child: Text( + 'Redeem Your Coupons'.tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), + ), + Center( + child: Container( + padding: const EdgeInsets.only( + top: 10, + left: 22, + right: 22, + ), + child: Text( + "Voucher or Coupon code".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), + ), + Container( + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 20, + ), child: DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(12), color: AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(12), + color: AppThemeData.primary300, + ), child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(12)), + borderRadius: const BorderRadius.all( + Radius.circular(12), + ), child: Container( padding: const EdgeInsets.all(20), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, alignment: Alignment.center, child: TextFormField( textAlign: TextAlign.center, - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), controller: controller.couponTextController.value, decoration: InputDecoration( border: InputBorder.none, hintText: "Write Coupon Code".tr(), - hintStyle: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400), + hintStyle: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey400, + ), ), ), ), @@ -880,27 +2004,47 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.only(top: 30, bottom: 30, left: 15, right: 15), + padding: const EdgeInsets.only( + top: 30, + bottom: 30, + left: 15, + right: 15, + ), child: RoundedButtonFill( title: "REDEEM NOW".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () { - final inputCode = controller.couponTextController.value.text.trim().toLowerCase(); + final inputCode = + controller.couponTextController.value.text + .trim() + .toLowerCase(); print("Entered code: $inputCode"); - print("Available coupons: ${controller.couponList.map((e) => e.code).toList()}"); + print( + "Available coupons: ${controller.couponList.map((e) => e.code).toList()}", + ); - final matchingCoupon = controller.couponList.firstWhereOrNull((c) => (c.code ?? '').trim().toLowerCase() == inputCode); + final matchingCoupon = controller.couponList + .firstWhereOrNull( + (c) => + (c.code ?? '').trim().toLowerCase() == + inputCode, + ); if (matchingCoupon != null) { print("✅ Coupon matched: ${matchingCoupon.code}"); controller.applyCoupon(matchingCoupon); - Future.delayed(const Duration(milliseconds: 300), () { - Get.back(); - }); + Future.delayed( + const Duration(milliseconds: 300), + () { + Get.back(); + }, + ); } else { print("❌ No matching coupon found"); - ShowToastDialog.showToast("Applied coupon not valid.".tr()); + ShowToastDialog.showToast( + "Applied coupon not valid.".tr(), + ); } }, ), @@ -920,7 +2064,9 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100), + border: Border.all( + color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, + ), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, ), child: Column( @@ -929,12 +2075,15 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { rowText( "Price".tr(), //Constant.amountShow(amount: controller.price.value.toString()), - controller.onProviderOrder.value?.provider.disPrice == "" || controller.onProviderOrder.value?.provider.disPrice == "0" + controller.onProviderOrder.value?.provider.disPrice == "" || + controller.onProviderOrder.value?.provider.disPrice == "0" ? "${Constant.amountShow(amount: controller.onProviderOrder.value?.provider.price.toString())} × ${controller.onProviderOrder.value?.quantity.toStringAsFixed(2)} ${Constant.amountShow(amount: controller.price.value.toString())}" : "${Constant.amountShow(amount: controller.onProviderOrder.value?.provider.disPrice.toString())} × ${controller.onProviderOrder.value?.quantity.toStringAsFixed(2)} ${Constant.amountShow(amount: controller.price.value.toString())}", isDark, ), - controller.discountAmount.value != 0 ? const Divider() : const SizedBox(), + controller.discountAmount.value != 0 + ? const Divider() + : const SizedBox(), controller.discountAmount.value != 0 ? Padding( padding: const EdgeInsets.symmetric(horizontal: 10), @@ -947,19 +2096,39 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { children: [ Text( "${"Discount".tr()} ${controller.discountType.value == 'Percentage' || controller.discountType.value == 'Percent' ? "(${controller.discountLabel.value}%)" : "(${Constant.amountShow(amount: controller.discountLabel.value)})"}", - style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: TextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + controller.offerCode.value, + style: TextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), - Text(controller.offerCode.value, style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ], ), ), - Text("(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})", style: const TextStyle(color: Colors.red)), + Text( + "(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})", + style: const TextStyle(color: Colors.red), + ), ], ), ) : const SizedBox(), const Divider(), - rowText("SubTotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark), + rowText( + "SubTotal".tr(), + Constant.amountShow(amount: controller.subTotal.value.toString()), + isDark, + ), const Divider(), ListView.builder( itemCount: Constant.taxList.length, @@ -970,19 +2139,39 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 10, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( "${taxModel.title} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})", - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ), Text( - Constant.amountShow(amount: Constant.getTaxValue(amount: controller.subTotal.value.toString(), taxModel: taxModel).toString()), - style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + Constant.getTaxValue( + amount: + controller.subTotal.value.toString(), + taxModel: taxModel, + ).toString(), + ), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -993,7 +2182,13 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { }, ), // Total Amount - rowText("Total Amount".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark), + rowText( + "Total Amount".tr(), + Constant.amountShow( + amount: controller.totalAmount.value.toString(), + ), + isDark, + ), const SizedBox(height: 5), ], ), @@ -1007,28 +2202,55 @@ class OnDemandOrderDetailsScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title, style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(value, style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.mediumTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + value, + style: AppThemeData.mediumTextStyle( + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ), ); } - Future showCancelBookingDialog(OnDemandOrderDetailsController controller, bool isDark) { + Future showCancelBookingDialog( + OnDemandOrderDetailsController controller, + bool isDark, + ) { return Get.dialog( AlertDialog( backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - title: Text('Please give reason for canceling this Booking'.tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + title: Text( + 'Please give reason for canceling this Booking'.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), content: TextFormField( controller: controller.cancelBookingController.value, maxLines: 5, - decoration: InputDecoration(hintText: "Specify your reason here".tr(), border: OutlineInputBorder(borderRadius: BorderRadius.circular(7))), + decoration: InputDecoration( + hintText: "Specify your reason here".tr(), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(7)), + ), ), actions: [ - TextButton(onPressed: () => Get.back(), child: Text('Cancel'.tr(), style: TextStyle(color: Colors.red))), + TextButton( + onPressed: () => Get.back(), + child: Text('Cancel'.tr(), style: TextStyle(color: Colors.red)), + ), TextButton( onPressed: () async { - if (controller.cancelBookingController.value.text.trim().isEmpty) { + if (controller.cancelBookingController.value.text + .trim() + .isEmpty) { ShowToastDialog.showToast("Please enter reason".tr()); } else { await controller.cancelBooking(); diff --git a/lib/screen_ui/on_demand_service/on_demand_payment_screen.dart b/lib/screen_ui/on_demand_service/on_demand_payment_screen.dart index dd6854a..c99539a 100644 --- a/lib/screen_ui/on_demand_service/on_demand_payment_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_payment_screen.dart @@ -1,7 +1,7 @@ import 'package:customer/constant/constant.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/0n_demand_payment_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../payment/createRazorPayOrderModel.dart'; @@ -35,12 +35,30 @@ class OnDemandPaymentScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Select Payment Method".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Select Payment Method".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -49,45 +67,106 @@ class OnDemandPaymentScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.greyDark200 : Colors.white), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), + decoration: BoxDecoration( + color: isDark ? AppThemeData.greyDark200 : Colors.white, + ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Preferred Payment".tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Preferred Payment".tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == + true || + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == + true || + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true) Column( children: [ const SizedBox(height: 10), Text( "Other Payment Options".tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), ), const SizedBox(height: 10), ], @@ -95,38 +174,155 @@ class OnDemandPaymentScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), Visibility( - visible: controller.payStackModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png"), + visible: + controller + .stripeModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller + .payPalModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller + .payStackModel + .value + .isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), Visibility( - visible: controller.razorPayModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"), + visible: + controller + .mercadoPagoModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), ), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller + .flutterWaveModel + .value + .isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller + .payFastModel + .value + .isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller + .razorPayModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller + .orangeMoneyModel + .value + .enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -137,55 +333,151 @@ class OnDemandPaymentScreen extends StatelessWidget { color: AppThemeData.primary300, textColor: AppThemeData.grey900, onPress: () async { - print("getTotalAmount :::::::: ${"${controller.totalAmount.value}"}"); + print( + "getTotalAmount :::::::: ${"${controller.totalAmount.value}"}", + ); if (controller.isOrderPlaced.value == false) { controller.isOrderPlaced.value = true; - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet("${controller.totalAmount.value}", context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment("${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { - double totalAmount = double.parse("${controller.totalAmount.value}"); - double walletAmount = double.tryParse(Constant.userModel?.walletAmount?.toString() ?? "0") ?? 0; + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + "${controller.totalAmount.value}", + context, + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.wallet.name) { + double totalAmount = double.parse( + "${controller.totalAmount.value}", + ); + double walletAmount = + double.tryParse( + Constant.userModel?.walletAmount + ?.toString() ?? + "0", + ) ?? + 0; if (walletAmount == 0) { - ShowToastDialog.showToast("Wallet balance is 0. Please recharge wallet.".tr()); + ShowToastDialog.showToast( + "Wallet balance is 0. Please recharge wallet." + .tr(), + ); } else if (walletAmount < totalAmount) { - ShowToastDialog.showToast("Insufficient wallet balance. Please add funds.".tr()); + ShowToastDialog.showToast( + "Insufficient wallet balance. Please add funds." + .tr(), + ); } else { controller.placeOrder(); } - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.cod.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.wallet.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, "${controller.totalAmount.value}"); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse("${controller.totalAmount.value}"), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: "${controller.totalAmount.value}", orderId: result.id); - } - }); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + "${controller.totalAmount.value}", + ); + } else if (controller + .selectedPaymentMethod + .value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + "${controller.totalAmount.value}", + ), + razorpayModel: + controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel result = + value; + controller.openCheckout( + amount: + "${controller.totalAmount.value}", + orderId: result.id, + ); + } + }); } else { controller.isOrderPlaced.value = false; - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } controller.isOrderPlaced.value = false; } @@ -215,8 +507,21 @@ class OnDemandPaymentScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -227,12 +532,30 @@ class OnDemandPaymentScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: Constant.userModel?.walletAmount == null ? '0.0' : Constant.userModel?.walletAmount.toString()), + Constant.amountShow( + amount: + Constant.userModel?.walletAmount == null + ? '0.0' + : Constant.userModel?.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -241,14 +564,23 @@ class OnDemandPaymentScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/on_demand_service/on_demand_review_screen.dart b/lib/screen_ui/on_demand_service/on_demand_review_screen.dart index f108a20..0b7a998 100644 --- a/lib/screen_ui/on_demand_service/on_demand_review_screen.dart +++ b/lib/screen_ui/on_demand_service/on_demand_review_screen.dart @@ -1,7 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/on_demand_review_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -34,61 +34,139 @@ class OnDemandReviewScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text(controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + controller.ratingModel.value != null + ? "Update Review".tr() + : "Add Review".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), ), body: Obx( () => - (controller.reviewFor.value == "Worker" && controller.workerModel.value == null) || (controller.reviewFor.value == "Provider" && controller.provider.value == null) + (controller.reviewFor.value == "Worker" && + controller.workerModel.value == null) || + (controller.reviewFor.value == "Provider" && + controller.provider.value == null) ? Constant.loader() : Padding( padding: const EdgeInsets.only(top: 50.0), child: Stack( children: [ Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 42, bottom: 20), + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 42, + bottom: 20, + ), child: Card( elevation: 2, - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(top: 65), child: Column( children: [ - Text('Rate for'.tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), Text( - controller.reviewFor.value == "Provider" ? controller.order.value!.provider.authorName ?? "" : controller.workerModel.value!.fullName(), - style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + 'Rate for'.tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Text( + controller.reviewFor.value == "Provider" + ? controller + .order + .value! + .provider + .authorName ?? + "" + : controller.workerModel.value! + .fullName(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), Padding( padding: const EdgeInsets.only(top: 10), child: RatingBar.builder( - initialRating: controller.ratings.value, + initialRating: + controller.ratings.value, minRating: 1, direction: Axis.horizontal, allowHalfRating: true, itemCount: 5, - itemPadding: const EdgeInsets.symmetric(horizontal: 4.0), - itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber), - unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, + itemPadding: + const EdgeInsets.symmetric( + horizontal: 4.0, + ), + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: Colors.amber, + ), + unratedColor: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey400, onRatingUpdate: (rating) { controller.ratings.value = rating; }, ), ), - Padding(padding: EdgeInsets.all(20.0), child: TextFieldWidget(hintText: "Type comment....".tr(), controller: controller.comment, maxLine: 5)), + Padding( + padding: EdgeInsets.all(20.0), + child: TextFieldWidget( + hintText: "Type comment....".tr(), + controller: controller.comment, + maxLine: 5, + ), + ), Padding( padding: const EdgeInsets.all(20.0), child: RoundedButtonFill( - title: controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(), + title: + controller.ratingModel.value != + null + ? "Update Review".tr() + : "Add Review".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: controller.submitReview, @@ -105,7 +183,19 @@ class OnDemandReviewScreen extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.circular(50), child: NetworkImageWidget( - imageUrl: controller.reviewFor.value == "Provider" ? controller.order.value?.provider.authorProfilePic ?? '' : controller.workerModel.value?.profilePictureURL ?? '', + imageUrl: + controller.reviewFor.value == "Provider" + ? controller + .order + .value + ?.provider + .authorProfilePic ?? + '' + : controller + .workerModel + .value + ?.profilePictureURL ?? + '', fit: BoxFit.cover, height: 100, width: 100, diff --git a/lib/screen_ui/on_demand_service/provider_inbox_screen.dart b/lib/screen_ui/on_demand_service/provider_inbox_screen.dart index d582fc2..c0474bd 100644 --- a/lib/screen_ui/on_demand_service/provider_inbox_screen.dart +++ b/lib/screen_ui/on_demand_service/provider_inbox_screen.dart @@ -10,8 +10,7 @@ import 'package:customer/widget/firebase_pagination/src/fireStore_pagination.dar import 'package:customer/widget/firebase_pagination/src/models/view_type.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -25,10 +24,19 @@ class ProviderInboxScreen extends StatelessWidget { final isDark = themeController.isDark.value; return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Provider Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Provider Inbox".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: FirestorePagination( //item builder type is compulsory. @@ -40,8 +48,12 @@ class ProviderInboxScreen extends StatelessWidget { onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString()); + UserModel? customer = await FireStoreUtils.getUserProfile( + inboxModel.customerId.toString(), + ); + UserModel? restaurantUser = await FireStoreUtils.getUserProfile( + inboxModel.restaurantId.toString(), + ); ShowToastDialog.closeLoader(); Get.to( @@ -62,15 +74,23 @@ class ProviderInboxScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: NetworkImageWidget( - imageUrl: inboxModel.restaurantProfileImage.toString(), + imageUrl: + inboxModel.restaurantProfileImage.toString(), fit: BoxFit.cover, height: Responsive.height(6, context), width: Responsive.width(12, context), @@ -87,13 +107,29 @@ class ProviderInboxScreen extends StatelessWidget { child: Text( "${inboxModel.restaurantName}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ), Text( - Constant.timestampToDate(inboxModel.createdAt!), + Constant.timestampToDate( + inboxModel.createdAt!, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -101,7 +137,14 @@ class ProviderInboxScreen extends StatelessWidget { Text( "${inboxModel.lastMessage}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + ), ), ], ), @@ -116,7 +159,10 @@ class ProviderInboxScreen extends StatelessWidget { shrinkWrap: true, onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()), // orderBy is compulsory to enable pagination - query: FirebaseFirestore.instance.collection('chat_provider').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true), + query: FirebaseFirestore.instance + .collection('chat_provider') + .where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()) + .orderBy('createdAt', descending: true), //Change types customerId viewType: ViewType.list, initialLoader: Constant.loader(), diff --git a/lib/screen_ui/on_demand_service/provider_screen.dart b/lib/screen_ui/on_demand_service/provider_screen.dart index 02e9936..e38223b 100644 --- a/lib/screen_ui/on_demand_service/provider_screen.dart +++ b/lib/screen_ui/on_demand_service/provider_screen.dart @@ -3,7 +3,7 @@ import 'package:customer/screen_ui/on_demand_service/on_demand_home_screen.dart' import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/provider_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../models/provider_serivce_model.dart'; @@ -26,58 +26,114 @@ class ProviderScreen extends StatelessWidget { controller.isLoading.value ? Center(child: Constant.loader()) : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 50), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 50, + ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Center( child: - (controller.userModel.value?.profilePictureURL ?? "").isNotEmpty - ? CircleAvatar(backgroundImage: NetworkImage(controller.userModel.value?.profilePictureURL ?? ''), radius: 50.0) - : CircleAvatar(backgroundImage: NetworkImage(Constant.placeHolderImage), radius: 50.0), + (controller.userModel.value?.profilePictureURL ?? + "") + .isNotEmpty + ? CircleAvatar( + backgroundImage: NetworkImage( + controller + .userModel + .value + ?.profilePictureURL ?? + '', + ), + radius: 50.0, + ) + : CircleAvatar( + backgroundImage: NetworkImage( + Constant.placeHolderImage, + ), + radius: 50.0, + ), ), const SizedBox(height: 10), Text( controller.userModel.value?.fullName() ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 20, fontWeight: FontWeight.w900), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontFamily: AppThemeData.regular, + fontSize: 20, + fontWeight: FontWeight.w900, + ), ), const SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_mail.svg", color: isDark ? Colors.white : Colors.black), + SvgPicture.asset( + "assets/icons/ic_mail.svg", + color: isDark ? Colors.white : Colors.black, + ), const SizedBox(width: 6), Text( controller.userModel.value?.email ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontFamily: AppThemeData.regular, + fontSize: 14, + fontWeight: FontWeight.w500, + ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_mobile.svg", color: isDark ? Colors.white : Colors.black), + SvgPicture.asset( + "assets/icons/ic_mobile.svg", + color: isDark ? Colors.white : Colors.black, + ), const SizedBox(width: 6), Text( controller.userModel.value?.phoneNumber ?? '', - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontFamily: AppThemeData.regular, + fontSize: 14, + fontWeight: FontWeight.w500, + ), ), ], ), const SizedBox(height: 10), Container( - decoration: const BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.all(Radius.circular(16))), + decoration: const BoxDecoration( + color: AppThemeData.warning400, + borderRadius: BorderRadius.all(Radius.circular(16)), + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, size: 16, color: Colors.white), + const Icon( + Icons.star, + size: 16, + color: Colors.white, + ), const SizedBox(width: 3), Text( _getRating(controller), - style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white), + style: const TextStyle( + letterSpacing: 0.5, + fontSize: 12, + fontFamily: AppThemeData.regular, + fontWeight: FontWeight.w500, + color: Colors.white, + ), ), ], ), @@ -93,8 +149,14 @@ class ProviderScreen extends StatelessWidget { itemCount: controller.providerList.length, padding: EdgeInsets.zero, itemBuilder: (context, index) { - ProviderServiceModel data = controller.providerList[index]; - return ServiceView(provider: data, isDark: isDark, controller: controller.onDemandHomeController.value); + ProviderServiceModel data = + controller.providerList[index]; + return ServiceView( + provider: data, + isDark: isDark, + controller: + controller.onDemandHomeController.value, + ); }, ), ), @@ -107,8 +169,16 @@ class ProviderScreen extends StatelessWidget { } String _getRating(ProviderController controller) { - final reviewsCount = double.tryParse(controller.userModel.value?.reviewsCount?.toString() ?? "0") ?? 0; - final reviewsSum = double.tryParse(controller.userModel.value?.reviewsSum?.toString() ?? "0") ?? 0; + final reviewsCount = + double.tryParse( + controller.userModel.value?.reviewsCount?.toString() ?? "0", + ) ?? + 0; + final reviewsSum = + double.tryParse( + controller.userModel.value?.reviewsSum?.toString() ?? "0", + ) ?? + 0; if (reviewsCount == 0) return "0"; final avg = reviewsSum / reviewsCount; diff --git a/lib/screen_ui/on_demand_service/view_all_popular_service_screen.dart b/lib/screen_ui/on_demand_service/view_all_popular_service_screen.dart index b180048..287ddba 100644 --- a/lib/screen_ui/on_demand_service/view_all_popular_service_screen.dart +++ b/lib/screen_ui/on_demand_service/view_all_popular_service_screen.dart @@ -1,7 +1,7 @@ import 'package:customer/screen_ui/on_demand_service/on_demand_home_screen.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/theme_controller.dart'; import '../../controllers/view_all_popular_service_controller.dart'; @@ -32,12 +32,30 @@ class ViewAllPopularServiceScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("All Services".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "All Services".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -46,13 +64,29 @@ class ViewAllPopularServiceScreen extends StatelessWidget { controller.isLoading.value ? Constant.loader() : Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + padding: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 15, + ), child: Column( children: [ - TextFieldWidget(hintText: "Search Service".tr(), controller: controller.searchTextFiledController.value, onchange: (value) => controller.getFilterData(value.toString())), + TextFieldWidget( + hintText: "Search Service".tr(), + controller: + controller.searchTextFiledController.value, + onchange: + (value) => + controller.getFilterData(value.toString()), + ), const SizedBox(height: 15), controller.providerList.isEmpty - ? Expanded(child: Center(child: Constant.showEmptyView(message: "No service Found".tr()))) + ? Expanded( + child: Center( + child: Constant.showEmptyView( + message: "No service Found".tr(), + ), + ), + ) : Expanded( child: ListView.builder( itemCount: controller.providerList.length, @@ -60,8 +94,14 @@ class ViewAllPopularServiceScreen extends StatelessWidget { padding: EdgeInsets.zero, scrollDirection: Axis.vertical, itemBuilder: (context, index) { - ProviderServiceModel data = controller.providerList[index]; - return ServiceView(provider: data, isDark: isDark, controller: controller.onDemandHomeController.value); + ProviderServiceModel data = + controller.providerList[index]; + return ServiceView( + provider: data, + isDark: isDark, + controller: + controller.onDemandHomeController.value, + ); }, ), ), diff --git a/lib/screen_ui/on_demand_service/view_category_service_screen.dart b/lib/screen_ui/on_demand_service/view_category_service_screen.dart index e86e7d9..467d535 100644 --- a/lib/screen_ui/on_demand_service/view_category_service_screen.dart +++ b/lib/screen_ui/on_demand_service/view_category_service_screen.dart @@ -1,6 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/theme_controller.dart'; import '../../controllers/view_category_service_controller.dart'; @@ -32,12 +32,30 @@ class ViewCategoryServiceListScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text(controller.categoryTitle.value, style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + controller.categoryTitle.value, + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -48,14 +66,22 @@ class ViewCategoryServiceListScreen extends StatelessWidget { : controller.providerList.isEmpty ? Constant.showEmptyView(message: "No Service Found".tr()) : Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: ListView.builder( itemCount: controller.providerList.length, shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (context, index) { - ProviderServiceModel providerModel = controller.providerList[index]; - return ServiceView(isDark: isDark, provider: providerModel, controller: controller.onDemandHomeController.value); + ProviderServiceModel providerModel = + controller.providerList[index]; + return ServiceView( + isDark: isDark, + provider: providerModel, + controller: controller.onDemandHomeController.value, + ); }, ), ), diff --git a/lib/screen_ui/on_demand_service/worker_inbox_screen.dart b/lib/screen_ui/on_demand_service/worker_inbox_screen.dart index 4b32e36..e74599c 100644 --- a/lib/screen_ui/on_demand_service/worker_inbox_screen.dart +++ b/lib/screen_ui/on_demand_service/worker_inbox_screen.dart @@ -10,8 +10,7 @@ import 'package:customer/widget/firebase_pagination/src/fireStore_pagination.dar import 'package:customer/widget/firebase_pagination/src/models/view_type.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import '../../../controllers/theme_controller.dart'; import '../../../service/fire_store_utils.dart'; import '../../../themes/show_toast_dialog.dart'; @@ -25,10 +24,19 @@ class WorkerInboxScreen extends StatelessWidget { final isDark = themeController.isDark.value; return Scaffold( appBar: AppBar( - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, centerTitle: false, titleSpacing: 0, - title: Text("Worker Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)), + title: Text( + "Worker Inbox".tr(), + textAlign: TextAlign.start, + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), + ), ), body: FirestorePagination( //item builder type is compulsory. @@ -40,11 +48,17 @@ class WorkerInboxScreen extends StatelessWidget { onTap: () async { ShowToastDialog.showLoader("Please wait...".tr()); - UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString()); - UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString()); + UserModel? customer = await FireStoreUtils.getUserProfile( + inboxModel.customerId.toString(), + ); + UserModel? restaurantUser = await FireStoreUtils.getUserProfile( + inboxModel.restaurantId.toString(), + ); ShowToastDialog.closeLoader(); - print("customerId: ${inboxModel.customerId}, restaurantId: ${inboxModel.restaurantId}"); + print( + "customerId: ${inboxModel.customerId}, restaurantId: ${inboxModel.restaurantId}", + ); Get.to( const ChatScreen(), arguments: { @@ -63,15 +77,23 @@ class WorkerInboxScreen extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), child: Container( - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + decoration: ShapeDecoration( + color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(10)), + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), child: NetworkImageWidget( - imageUrl: inboxModel.restaurantProfileImage.toString(), + imageUrl: + inboxModel.restaurantProfileImage.toString(), fit: BoxFit.cover, height: Responsive.height(6, context), width: Responsive.width(12, context), @@ -88,13 +110,29 @@ class WorkerInboxScreen extends StatelessWidget { child: Text( "${inboxModel.restaurantName}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + ), ), ), Text( - Constant.timestampToDate(inboxModel.createdAt!), + Constant.timestampToDate( + inboxModel.createdAt!, + ), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: AppThemeData.regular, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData.grey500, + ), ), ], ), @@ -102,7 +140,14 @@ class WorkerInboxScreen extends StatelessWidget { Text( "${inboxModel.lastMessage}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 14, + color: + isDark + ? AppThemeData.grey200 + : AppThemeData.grey700, + ), ), ], ), @@ -117,7 +162,10 @@ class WorkerInboxScreen extends StatelessWidget { shrinkWrap: true, onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()), // orderBy is compulsory to enable pagination - query: FirebaseFirestore.instance.collection('chat_worker').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true), + query: FirebaseFirestore.instance + .collection('chat_worker') + .where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()) + .orderBy('createdAt', descending: true), //Change types customerId viewType: ViewType.list, initialLoader: Constant.loader(), diff --git a/lib/screen_ui/parcel_service/book_parcel_screen.dart b/lib/screen_ui/parcel_service/book_parcel_screen.dart index e60a814..cc14c4e 100644 --- a/lib/screen_ui/parcel_service/book_parcel_screen.dart +++ b/lib/screen_ui/parcel_service/book_parcel_screen.dart @@ -8,7 +8,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/book_parcel_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -43,8 +43,20 @@ class BookParcelScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -52,12 +64,21 @@ class BookParcelScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Book Your Document Delivery".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Book Your Document Delivery".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), Text( "Schedule a secure and timely pickup & delivery".tr(), maxLines: 1, overflow: TextOverflow.ellipsis, - style: AppThemeData.mediumTextStyle(fontSize: 12, color: AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 12, + color: AppThemeData.grey900, + ), ), ], ), @@ -84,7 +105,8 @@ class BookParcelScreen extends StatelessWidget { nameController: controller.senderNameController.value, mobileController: controller.senderMobileController.value, noteController: controller.senderNoteController.value, - countryCodeController: controller.senderCountryCodeController.value, + countryCodeController: + controller.senderCountryCodeController.value, showWeight: true, isDark: isDark, context: context, @@ -95,14 +117,25 @@ class BookParcelScreen extends StatelessWidget { if (result != null) { final firstPlace = result; - if (Constant.checkZoneCheck(firstPlace.coordinates.latitude, firstPlace.coordinates.longitude) == true) { + if (Constant.checkZoneCheck( + firstPlace.coordinates.latitude, + firstPlace.coordinates.longitude, + ) == + true) { final address = firstPlace.address; final lat = firstPlace.coordinates.latitude; final lng = firstPlace.coordinates.longitude; - controller.senderLocationController.value.text = address; // ✅ - controller.senderLocation.value = UserLocation(latitude: lat, longitude: lng); // ✅ <-- Add this + controller.senderLocationController.value.text = + address; // ✅ + controller.senderLocation.value = UserLocation( + latitude: lat, + longitude: lng, + ); // ✅ <-- Add this } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } } } else { @@ -110,11 +143,27 @@ class BookParcelScreen extends StatelessWidget { if (value != null) { SelectedLocationModel selectedLocationModel = value; - if (Constant.checkZoneCheck(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude) == true) { - controller.senderLocationController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.senderLocation.value = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); + if (Constant.checkZoneCheck( + selectedLocationModel.latLng!.latitude, + selectedLocationModel.latLng!.longitude, + ) == + true) { + controller + .senderLocationController + .value + .text = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + controller.senderLocation.value = UserLocation( + latitude: selectedLocationModel.latLng!.latitude, + longitude: + selectedLocationModel.latLng!.longitude, + ); } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } // ✅ <-- Add this } @@ -125,11 +174,13 @@ class BookParcelScreen extends StatelessWidget { const SizedBox(height: 16), buildInfoSectionView( title: "Receiver Information".tr(), - locationController: controller.receiverLocationController.value, + locationController: + controller.receiverLocationController.value, nameController: controller.receiverNameController.value, mobileController: controller.receiverMobileController.value, noteController: controller.receiverNoteController.value, - countryCodeController: controller.receiverCountryCodeController.value, + countryCodeController: + controller.receiverCountryCodeController.value, showWeight: false, isDark: isDark, context: context, @@ -140,15 +191,26 @@ class BookParcelScreen extends StatelessWidget { if (result != null) { final firstPlace = result; - if (Constant.checkZoneCheck(firstPlace.coordinates.latitude, firstPlace.coordinates.longitude) == true) { + if (Constant.checkZoneCheck( + firstPlace.coordinates.latitude, + firstPlace.coordinates.longitude, + ) == + true) { final lat = firstPlace.coordinates.latitude; final lng = firstPlace.coordinates.longitude; final address = firstPlace.address; - controller.receiverLocationController.value.text = address; // ✅ - controller.receiverLocation.value = UserLocation(latitude: lat, longitude: lng); + controller.receiverLocationController.value.text = + address; // ✅ + controller.receiverLocation.value = UserLocation( + latitude: lat, + longitude: lng, + ); } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } } } else { @@ -156,11 +218,27 @@ class BookParcelScreen extends StatelessWidget { if (value != null) { SelectedLocationModel selectedLocationModel = value; - if (Constant.checkZoneCheck(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude) == true) { - controller.receiverLocationController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.receiverLocation.value = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); // ✅ <-- Add this + if (Constant.checkZoneCheck( + selectedLocationModel.latLng!.latitude, + selectedLocationModel.latLng!.longitude, + ) == + true) { + controller + .receiverLocationController + .value + .text = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + controller.receiverLocation.value = UserLocation( + latitude: selectedLocationModel.latLng!.latitude, + longitude: + selectedLocationModel.latLng!.longitude, + ); // ✅ <-- Add this } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } } }); @@ -187,18 +265,30 @@ class BookParcelScreen extends StatelessWidget { ); } - Widget selectDeliveryTypeView(BookParcelController controller, bool isDark, BuildContext context) { + Widget selectDeliveryTypeView( + BookParcelController controller, + bool isDark, + BuildContext context, + ) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + border: Border.all( + color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + ), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Select delivery type".tr(), style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, fontSize: 13)), + Text( + "Select delivery type".tr(), + style: AppThemeData.boldTextStyle( + color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, + fontSize: 13, + ), + ), const SizedBox(height: 10), InkWell( onTap: () { @@ -207,12 +297,34 @@ class BookParcelScreen extends StatelessWidget { }, child: Row( children: [ - Image.asset("assets/images/image_parcel.png", height: 38, width: 38), + Image.asset( + "assets/images/image_parcel.png", + height: 38, + width: 38, + ), const SizedBox(width: 20), - Expanded(child: Text("As soon as possible".tr(), style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16))), + Expanded( + child: Text( + "As soon as possible".tr(), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), + ), Icon( - controller.selectedDeliveryType.value == 'now' ? Icons.radio_button_checked : Icons.radio_button_off, - color: controller.selectedDeliveryType.value == 'now' ? AppThemeData.primary300 : (isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + controller.selectedDeliveryType.value == 'now' + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: + controller.selectedDeliveryType.value == 'now' + ? AppThemeData.primary300 + : (isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500), size: 20, ), ], @@ -228,12 +340,34 @@ class BookParcelScreen extends StatelessWidget { children: [ Row( children: [ - Image.asset("assets/images/image_parcel_scheduled.png", height: 38, width: 38), + Image.asset( + "assets/images/image_parcel_scheduled.png", + height: 38, + width: 38, + ), const SizedBox(width: 20), - Expanded(child: Text("Scheduled".tr(), style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16))), + Expanded( + child: Text( + "Scheduled".tr(), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 16, + ), + ), + ), Icon( - controller.selectedDeliveryType.value == 'later' ? Icons.radio_button_checked : Icons.radio_button_off, - color: controller.selectedDeliveryType.value == 'later' ? AppThemeData.primary300 : (isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + controller.selectedDeliveryType.value == 'later' + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: + controller.selectedDeliveryType.value == 'later' + ? AppThemeData.primary300 + : (isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500), size: 20, ), ], @@ -246,9 +380,18 @@ class BookParcelScreen extends StatelessWidget { hintText: "When to pickup at this address".tr(), controller: controller.scheduledDateController.value, enable: false, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, - suffix: const Padding(padding: EdgeInsets.only(right: 10), child: Icon(Icons.calendar_month_outlined)), + backgroundColor: + isDark + ? AppThemeData.surfaceDark + : AppThemeData.surface, + borderColor: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + suffix: const Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.calendar_month_outlined), + ), ), ), const SizedBox(height: 10), @@ -259,9 +402,18 @@ class BookParcelScreen extends StatelessWidget { controller: controller.scheduledTimeController.value, enable: false, // onchange: (v) => controller.pickScheduledTime(context), - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, - suffix: const Padding(padding: EdgeInsets.only(right: 10), child: Icon(Icons.access_time)), + backgroundColor: + isDark + ? AppThemeData.surfaceDark + : AppThemeData.surface, + borderColor: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + suffix: const Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.access_time), + ), ), ), ], @@ -278,29 +430,75 @@ class BookParcelScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + border: Border.all( + color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + ), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Upload parcel image".tr(), style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, fontSize: 13)), + Text( + "Upload parcel image".tr(), + style: AppThemeData.boldTextStyle( + color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, + fontSize: 13, + ), + ), const SizedBox(height: 10), DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(10), + color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300, + ), child: Container( alignment: Alignment.center, - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + ), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/ic_upload_parcel.svg", height: 40, width: 40), + SvgPicture.asset( + "assets/icons/ic_upload_parcel.svg", + height: 40, + width: 40, + ), const SizedBox(height: 10), - Text("Upload Parcel Image".tr(), style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Upload Parcel Image".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 4), - Text("Supported: .jpg, .jpeg, .png".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), - Text("Max size 1MB".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + "Supported: .jpg, .jpeg, .png".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), + ), + Text( + "Max size 1MB".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), + ), const SizedBox(height: 8), RoundedButtonFill( title: "Browse Image".tr(), @@ -326,7 +524,15 @@ class BookParcelScreen extends StatelessWidget { children: [ Container( padding: const EdgeInsets.only(top: 20, right: 20), - child: ClipRRect(borderRadius: BorderRadius.circular(8), child: Image.file(File(image.path), width: 70, height: 70, fit: BoxFit.cover)), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.file( + File(image.path), + width: 70, + height: 70, + fit: BoxFit.cover, + ), + ), ), Positioned.fill( top: 0, @@ -334,7 +540,11 @@ class BookParcelScreen extends StatelessWidget { child: Align( alignment: Alignment.topRight, child: IconButton( - icon: const Icon(Icons.cancel, color: AppThemeData.danger300, size: 20), + icon: const Icon( + Icons.cancel, + color: AppThemeData.danger300, + size: 20, + ), onPressed: () { controller.images.remove(image); }, @@ -367,13 +577,21 @@ class BookParcelScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + border: Border.all( + color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + ), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title, style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, fontSize: 13)), + Text( + title, + style: AppThemeData.boldTextStyle( + color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, + fontSize: 13, + ), + ), const SizedBox(height: 10), GestureDetector( @@ -382,9 +600,14 @@ class BookParcelScreen extends StatelessWidget { hintText: "Your Location".tr(), controller: locationController, - suffix: const Padding(padding: EdgeInsets.only(right: 10), child: Icon(Icons.location_on_outlined)), - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + suffix: const Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.location_on_outlined), + ), + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + borderColor: + isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, enable: false, ), ), @@ -393,8 +616,10 @@ class BookParcelScreen extends StatelessWidget { TextFieldWidget( hintText: "Name".tr(), controller: nameController, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + borderColor: + isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, ), const SizedBox(height: 10), @@ -402,24 +627,49 @@ class BookParcelScreen extends StatelessWidget { hintText: "Enter Mobile number".tr(), controller: mobileController, textInputType: TextInputType.number, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9]')), LengthLimitingTextInputFormatter(10)], - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9]')), + LengthLimitingTextInputFormatter(10), + ], + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + borderColor: + isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, prefix: Row( mainAxisSize: MainAxisSize.min, children: [ CountryCodePicker( onChanged: (value) { - countryCodeController.text = value.dialCode ?? Constant.defaultCountryCode; + countryCodeController.text = + value.dialCode ?? Constant.defaultCountryCode; }, - initialSelection: countryCodeController.text.isNotEmpty ? countryCodeController.text : Constant.defaultCountryCode, + initialSelection: + countryCodeController.text.isNotEmpty + ? countryCodeController.text + : Constant.defaultCountryCode, showCountryOnly: false, showOnlyCountryWhenClosed: false, alignLeft: false, - textStyle: TextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : Colors.black), - dialogTextStyle: TextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), - searchStyle: TextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), - dialogBackgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + textStyle: TextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark900 : Colors.black, + ), + dialogTextStyle: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + searchStyle: TextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + dialogBackgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, padding: EdgeInsets.zero, ), // const Icon(Icons.keyboard_arrow_down_rounded, size: 24, color: AppThemeData.grey400), @@ -437,19 +687,37 @@ class BookParcelScreen extends StatelessWidget { enableSearch: false, textFieldDecoration: InputDecoration( hintText: "Select parcel Weight".tr(), - hintStyle: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.grey400 : AppThemeData.greyDark400), + hintStyle: AppThemeData.regularTextStyle( + fontSize: 14, + color: + isDark ? AppThemeData.grey400 : AppThemeData.greyDark400, + ), filled: true, - fillColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: AppThemeData.grey200)), - enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: AppThemeData.grey200)), - focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: AppThemeData.grey200)), + fillColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: AppThemeData.grey200), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: AppThemeData.grey200), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: AppThemeData.grey200), + ), ), dropDownList: controller.parcelWeight.map((e) { return DropDownValueModel( name: e.title ?? 'Normal'.tr(), - value: e.title ?? 'Normal'.tr(), // safer to use title string + value: + e.title ?? 'Normal'.tr(), // safer to use title string ); }).toList(), onChanged: (val) { @@ -457,7 +725,8 @@ class BookParcelScreen extends StatelessWidget { controller.senderWeightController.value.setDropDown(val); // Link it to the selectedWeight object - controller.selectedWeight = controller.parcelWeight.firstWhereOrNull((e) => e.title == val.value); + controller.selectedWeight = controller.parcelWeight + .firstWhereOrNull((e) => e.title == val.value); } }, ), @@ -467,8 +736,10 @@ class BookParcelScreen extends StatelessWidget { TextFieldWidget( hintText: "Notes (Optional)".tr(), controller: noteController, - backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface, - borderColor: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, + backgroundColor: + isDark ? AppThemeData.surfaceDark : AppThemeData.surface, + borderColor: + isDark ? AppThemeData.greyDark200 : AppThemeData.grey200, ), ], ), diff --git a/lib/screen_ui/parcel_service/home_parcel_screen.dart b/lib/screen_ui/parcel_service/home_parcel_screen.dart index 16e2437..b9ad4e1 100644 --- a/lib/screen_ui/parcel_service/home_parcel_screen.dart +++ b/lib/screen_ui/parcel_service/home_parcel_screen.dart @@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/home_parcel_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../models/banner_model.dart'; @@ -46,8 +46,20 @@ class HomeParcelScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -60,9 +72,21 @@ class HomeParcelScreen extends StatelessWidget { onTap: () { Get.offAll(const LoginScreen()); }, - child: Text("Login".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900)), + child: Text( + "Login".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), + ), ) - : Text(Constant.userModel!.fullName(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900)), + : Text( + Constant.userModel!.fullName(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), + ), InkWell( onTap: () async { if (Constant.userModel != null) { @@ -75,9 +99,12 @@ class HomeParcelScreen extends StatelessWidget { } else { Constant.checkPermission( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); - ShippingAddress shippingAddress = ShippingAddress(); + ShippingAddress shippingAddress = + ShippingAddress(); try { await Geolocator.requestPermission(); @@ -85,40 +112,71 @@ class HomeParcelScreen extends StatelessWidget { ShowToastDialog.closeLoader(); if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; + final lat = + firstPlace.coordinates.latitude; + final lng = + firstPlace.coordinates.longitude; final address = firstPlace.address; shippingAddress.addressAs = "Home"; - shippingAddress.locality = address.toString(); - shippingAddress.location = UserLocation(latitude: lat, longitude: lng); + shippingAddress.locality = + address.toString(); + shippingAddress.location = UserLocation( + latitude: lat, + longitude: lng, + ); - Constant.selectedLocation = shippingAddress; + Constant.selectedLocation = + shippingAddress; Get.back(); } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; shippingAddress.addressAs = "Home"; - shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude); - shippingAddress.locality = "Picked from Map"; + shippingAddress + .location = UserLocation( + latitude: + selectedLocationModel + .latLng! + .latitude, + longitude: + selectedLocationModel + .latLng! + .longitude, + ); + shippingAddress.locality = + "Picked from Map"; - Constant.selectedLocation = shippingAddress; + Constant.selectedLocation = + shippingAddress; } }); } } catch (e) { - await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) { + await placemarkFromCoordinates( + 19.228825, + 72.854118, + ).then((valuePlaceMaker) { Placemark placeMark = valuePlaceMaker[0]; - shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118); + shippingAddress.location = UserLocation( + latitude: 19.228825, + longitude: 72.854118, + ); String currentLocation = "${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}"; - shippingAddress.locality = currentLocation; + shippingAddress.locality = + currentLocation; }); Constant.selectedLocation = shippingAddress; @@ -133,7 +191,10 @@ class HomeParcelScreen extends StatelessWidget { Constant.selectedLocation.getFullAddress(), maxLines: 1, overflow: TextOverflow.ellipsis, - style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), ), ), ], @@ -160,22 +221,46 @@ class HomeParcelScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("What are you sending?".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "What are you sending?".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 12), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), + ), + padding: const EdgeInsets.symmetric( + horizontal: 20, ), - padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView.builder( itemCount: controller.parcelCategory.length, shrinkWrap: true, physics: const ScrollPhysics(), - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), itemBuilder: (context, index) { - return buildItems(item: controller.parcelCategory[index], isDark: isDark); + return buildItems( + item: controller.parcelCategory[index], + isDark: isDark, + ); }, ), ), @@ -199,16 +284,36 @@ class HomeParcelScreen extends StatelessWidget { if (Constant.userModel == null) { Get.to(const LoginScreen()); } else { - Get.to(const BookParcelScreen(), arguments: {'parcelCategory': item}); + Get.to( + const BookParcelScreen(), + arguments: {'parcelCategory': item}, + ); } }, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - NetworkImageWidget(imageUrl: item.image ?? '', height: 38, width: 38), + NetworkImageWidget( + imageUrl: item.image ?? '', + height: 38, + width: 38, + ), const SizedBox(width: 20), - Expanded(child: Text(item.title ?? '', style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16))), - Icon(Icons.arrow_forward_ios, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, size: 20), + Expanded( + child: Text( + item.title ?? '', + style: AppThemeData.semiBoldTextStyle( + color: + isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + fontSize: 16, + ), + ), + ), + Icon( + Icons.arrow_forward_ios, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + size: 20, + ), ], ), ), @@ -256,7 +361,13 @@ class BannerView extends StatelessWidget { final banner = bannerList[index]; return ClipRRect( borderRadius: BorderRadius.circular(15), - child: SizedBox(width: MediaQuery.of(context).size.width * 0.8, child: NetworkImageWidget(imageUrl: banner.photo ?? '', fit: BoxFit.cover)), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + child: NetworkImageWidget( + imageUrl: banner.photo ?? '', + fit: BoxFit.cover, + ), + ), ); }, ), @@ -266,7 +377,18 @@ class BannerView extends StatelessWidget { return Row( children: List.generate(bannerList.length, (index) { bool isSelected = currentPage.value == index; - return Expanded(child: Container(height: 4, decoration: BoxDecoration(color: isSelected ? AppThemeData.grey300 : AppThemeData.grey100, borderRadius: BorderRadius.circular(5)))); + return Expanded( + child: Container( + height: 4, + decoration: BoxDecoration( + color: + isSelected + ? AppThemeData.grey300 + : AppThemeData.grey100, + borderRadius: BorderRadius.circular(5), + ), + ), + ); }), ); }), diff --git a/lib/screen_ui/parcel_service/my_booking_screen.dart b/lib/screen_ui/parcel_service/my_booking_screen.dart index c1f00d5..25c4509 100644 --- a/lib/screen_ui/parcel_service/my_booking_screen.dart +++ b/lib/screen_ui/parcel_service/my_booking_screen.dart @@ -3,7 +3,7 @@ import 'package:customer/screen_ui/parcel_service/parcel_order_details.dart'; import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/parcel_my_booking_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -23,14 +23,27 @@ class MyBookingScreen extends StatelessWidget { builder: (controller) { return DefaultTabController( length: controller.tabTitles.length, - initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value), + initialIndex: controller.tabTitles.indexOf( + controller.selectedTab.value, + ), child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: AppThemeData.primary300, title: Padding( padding: const EdgeInsets.only(bottom: 10), - child: Row(children: [const SizedBox(width: 10), Text("Parcel History".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900))]), + child: Row( + children: [ + const SizedBox(width: 10), + Text( + "Parcel History".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + ], + ), ), bottom: TabBar( // don't re-subscribe onTap — just update selectedTab (optional) @@ -41,8 +54,13 @@ class MyBookingScreen extends StatelessWidget { labelColor: AppThemeData.parcelService500, unselectedLabelColor: AppThemeData.parcelService500, labelStyle: AppThemeData.boldTextStyle(fontSize: 15), - unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 15), - tabs: controller.tabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(), + unselectedLabelStyle: AppThemeData.mediumTextStyle( + fontSize: 15, + ), + tabs: + controller.tabTitles + .map((title) => Tab(child: Center(child: Text(title)))) + .toList(), ), ), @@ -56,12 +74,30 @@ class MyBookingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "Please Log In to Continue".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -83,7 +119,17 @@ class MyBookingScreen extends StatelessWidget { final orders = controller.getOrdersForTab(title); if (orders.isEmpty) { - return Center(child: Text("No orders found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))); + return Center( + child: Text( + "No orders found".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ); } return ListView.builder( @@ -93,55 +139,98 @@ class MyBookingScreen extends StatelessWidget { final order = orders[index]; return GestureDetector( onTap: () { - Get.to(() => const ParcelOrderDetails(), arguments: order); + Get.to( + () => const ParcelOrderDetails(), + arguments: order, + ); }, child: Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, borderRadius: BorderRadius.circular(15), - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(bottom: 8.0), + padding: const EdgeInsets.only( + bottom: 8.0, + ), child: Text( "${'Order Date:'.tr()}${order.isSchedule == true ? controller.formatDate(order.createdAt!) : controller.formatDate(order.senderPickupDateTime!)}", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.info400, + ), ), ), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Column( children: [ - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), - DottedBorder( - options: CustomPathDottedBorderOptions( - color: Colors.grey.shade400, - strokeWidth: 2, - dashPattern: [4, 4], - customPath: - (size) => - Path() - ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), - ), - child: const SizedBox(width: 20, height: 95), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, + ), + DottedBorder( + options: + CustomPathDottedBorderOptions( + color: + Colors + .grey + .shade400, + strokeWidth: 2, + dashPattern: [4, 4], + customPath: + (size) => + Path() + ..moveTo( + size.width / + 2, + 0, + ) + ..lineTo( + size.width / + 2, + size.height, + ), + ), + child: const SizedBox( + width: 20, + height: 95, + ), + ), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, ), - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), ], ), const SizedBox(width: 12), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ _infoSection( - "Pickup Address (Sender):".tr(), + "Pickup Address (Sender):" + .tr(), order.sender?.name ?? '', order.sender?.address ?? '', order.sender?.phone ?? '', @@ -153,9 +242,11 @@ class MyBookingScreen extends StatelessWidget { ), const SizedBox(height: 16), _infoSection( - "Delivery Address (Receiver):".tr(), + "Delivery Address (Receiver):" + .tr(), order.receiver?.name ?? '', - order.receiver?.address ?? '', + order.receiver?.address ?? + '', order.receiver?.phone ?? '', // order.receiverPickupDateTime != null // ? "Delivery Time: ${controller.formatDate(order.receiverPickupDateTime!)}" @@ -182,27 +273,74 @@ class MyBookingScreen extends StatelessWidget { ); } - Widget _infoSection(String title, String name, String address, String phone, String? status, bool isDark) { + Widget _infoSection( + String title, + String name, + String address, + String phone, + String? status, + bool isDark, + ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( - child: Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), maxLines: 1, overflow: TextOverflow.ellipsis), + child: Text( + title, + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), ), if (status != null) ...[ Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), - decoration: BoxDecoration(color: AppThemeData.info50, border: Border.all(color: AppThemeData.info300), borderRadius: BorderRadius.circular(12)), - child: Text(status, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)), + padding: const EdgeInsets.symmetric( + vertical: 6, + horizontal: 12, + ), + decoration: BoxDecoration( + color: AppThemeData.info50, + border: Border.all(color: AppThemeData.info300), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + status, + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.info500, + ), + ), ), ], ], ), - Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + name, + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + address, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + phone, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), //Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ], ); diff --git a/lib/screen_ui/parcel_service/order_successfully_placed.dart b/lib/screen_ui/parcel_service/order_successfully_placed.dart index a4ff870..cbccb86 100644 --- a/lib/screen_ui/parcel_service/order_successfully_placed.dart +++ b/lib/screen_ui/parcel_service/order_successfully_placed.dart @@ -1,7 +1,7 @@ import 'package:customer/screen_ui/parcel_service/parcel_dashboard_screen.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:customer/themes/app_them_data.dart'; import 'package:customer/themes/round_button_fill.dart'; import '../../controllers/parcel_dashboard_controller.dart'; @@ -24,13 +24,21 @@ class OrderSuccessfullyPlaced extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Image.asset("assets/images/parcel_order_successfully_placed.png"), + Image.asset( + "assets/images/parcel_order_successfully_placed.png", + ), const SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: Text( "Your Order Has Been Placed!".tr(), - style: AppThemeData.boldTextStyle(fontSize: 22, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.boldTextStyle( + fontSize: 22, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), textAlign: TextAlign.center, ), ), @@ -38,8 +46,15 @@ class OrderSuccessfullyPlaced extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 50), child: Text( - "We’ve received your parcel booking and it’s now being processed. You can track its status in real time.".tr(), - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + "We’ve received your parcel booking and it’s now being processed. You can track its status in real time." + .tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), textAlign: TextAlign.center, ), ), @@ -50,7 +65,9 @@ class OrderSuccessfullyPlaced extends StatelessWidget { print("Tracking Order: $parcelOrder"); //Get.to(() => TrackOrderScreen(), arguments: {'order': parcelOrder}); Get.offAll(const ParcelDashboardScreen()); - ParcelDashboardController controller = Get.put(ParcelDashboardController()); + ParcelDashboardController controller = Get.put( + ParcelDashboardController(), + ); controller.selectedIndex.value = 1; }, color: AppThemeData.primary300, diff --git a/lib/screen_ui/parcel_service/parcel_coupon_screen.dart b/lib/screen_ui/parcel_service/parcel_coupon_screen.dart index 7c372ae..5393cc6 100644 --- a/lib/screen_ui/parcel_service/parcel_coupon_screen.dart +++ b/lib/screen_ui/parcel_service/parcel_coupon_screen.dart @@ -8,7 +8,7 @@ import 'package:customer/widget/my_separator.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ParcelCouponScreen extends StatelessWidget { const ParcelCouponScreen({super.key}); @@ -33,12 +33,30 @@ class ParcelCouponScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Coupon".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Coupon".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -54,17 +72,35 @@ class ParcelCouponScreen extends StatelessWidget { itemBuilder: (context, index) { CouponModel couponModel = controller.cabCouponList[index]; return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Container( height: Responsive.height(16, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), child: Stack( children: [ - Image.asset("assets/images/ic_coupon_image.png", height: Responsive.height(16, context), fit: BoxFit.fill), + Image.asset( + "assets/images/ic_coupon_image.png", + height: Responsive.height(16, context), + fit: BoxFit.fill, + ), Padding( padding: const EdgeInsets.only(left: 10), child: Align( @@ -74,7 +110,14 @@ class ParcelCouponScreen extends StatelessWidget { child: Text( "${couponModel.discountType == "Fix Price" ? Constant.amountShow(amount: couponModel.discount) : "${couponModel.discount}%"} ${'Off'.tr()}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), ), ), @@ -84,24 +127,53 @@ class ParcelCouponScreen extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(6), color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + options: + RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular( + 6, + ), + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), child: Text( "${couponModel.code}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), ), ), ), - const Expanded(child: SizedBox(height: 10)), + const Expanded( + child: SizedBox(height: 10), + ), InkWell( onTap: () { Get.back(result: couponModel); @@ -109,18 +181,38 @@ class ParcelCouponScreen extends StatelessWidget { child: Text( "Tap To Apply".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ], ), const SizedBox(height: 20), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 20), Text( "${couponModel.description}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), diff --git a/lib/screen_ui/parcel_service/parcel_dashboard_screen.dart b/lib/screen_ui/parcel_service/parcel_dashboard_screen.dart index 97744c2..2fe7a4a 100644 --- a/lib/screen_ui/parcel_service/parcel_dashboard_screen.dart +++ b/lib/screen_ui/parcel_service/parcel_dashboard_screen.dart @@ -5,7 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class ParcelDashboardScreen extends StatelessWidget { const ParcelDashboardScreen({super.key}); @@ -25,12 +25,21 @@ class ParcelDashboardScreen extends StatelessWidget { showUnselectedLabels: true, showSelectedLabels: true, selectedFontSize: 12, - selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), - unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), + selectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), + unselectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), currentIndex: controller.selectedIndex.value, - backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - selectedItemColor: isDark ? AppThemeData.parcelServiceDark300 : AppThemeData.primary300, - unselectedItemColor: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, + backgroundColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + selectedItemColor: + isDark + ? AppThemeData.parcelServiceDark300 + : AppThemeData.primary300, + unselectedItemColor: + isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, onTap: (int index) { if (index == 0) { Get.put(ParcelDashboardController()); @@ -40,15 +49,57 @@ class ParcelDashboardScreen extends StatelessWidget { items: Constant.walletSetting == false ? [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_parcel.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_mybooking_parcel.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_profile_parcel.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_parcel.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_mybooking_parcel.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_profile_parcel.svg", + label: 'Profile'.tr(), + controller: controller, + ), ] : [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_parcel.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_mybooking_parcel.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_wallet_parcel.svg", label: 'Wallet'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile_parcel.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_parcel.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_mybooking_parcel.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_wallet_parcel.svg", + label: 'Wallet'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_profile_parcel.svg", + label: 'Profile'.tr(), + controller: controller, + ), ], ), ); @@ -57,7 +108,13 @@ class ParcelDashboardScreen extends StatelessWidget { }); } - BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required ParcelDashboardController controller}) { + BottomNavigationBarItem navigationBarItem( + isDark, { + required int index, + required String label, + required String assetIcon, + required ParcelDashboardController controller, + }) { return BottomNavigationBarItem( icon: Padding( padding: const EdgeInsets.symmetric(vertical: 5), diff --git a/lib/screen_ui/parcel_service/parcel_order_confirmation.dart b/lib/screen_ui/parcel_service/parcel_order_confirmation.dart index a53ea1a..1d76a34 100644 --- a/lib/screen_ui/parcel_service/parcel_order_confirmation.dart +++ b/lib/screen_ui/parcel_service/parcel_order_confirmation.dart @@ -4,7 +4,7 @@ import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/parcel_order_confirmation_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -38,12 +38,30 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Order Confirmation".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Order Confirmation".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -60,8 +78,16 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Row( @@ -70,7 +96,11 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { // Timeline with icons and line Column( children: [ - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, + ), DottedBorder( options: CustomPathDottedBorderOptions( color: Colors.grey.shade400, @@ -80,11 +110,21 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { (size) => Path() ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), + ..lineTo( + size.width / 2, + size.height, + ), + ), + child: const SizedBox( + width: 20, + height: 95, ), - child: const SizedBox(width: 20, height: 95), ), - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, + ), ], ), const SizedBox(width: 12), @@ -95,9 +135,24 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { children: [ _infoSection( "Pickup Address (Sender):".tr(), - controller.parcelOrder.value.sender?.name ?? '', - controller.parcelOrder.value.sender?.address ?? '', - controller.parcelOrder.value.sender?.phone ?? '', + controller + .parcelOrder + .value + .sender + ?.name ?? + '', + controller + .parcelOrder + .value + .sender + ?.address ?? + '', + controller + .parcelOrder + .value + .sender + ?.phone ?? + '', // controller.parcelOrder.value.senderPickupDateTime != null // ? "Pickup Time: ${controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}" // : '', @@ -106,9 +161,24 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { const SizedBox(height: 16), _infoSection( "Delivery Address (Receiver):".tr(), - controller.parcelOrder.value.receiver?.name ?? '', - controller.parcelOrder.value.receiver?.address ?? '', - controller.parcelOrder.value.receiver?.phone ?? '', + controller + .parcelOrder + .value + .receiver + ?.name ?? + '', + controller + .parcelOrder + .value + .receiver + ?.address ?? + '', + controller + .parcelOrder + .value + .receiver + ?.phone ?? + '', // controller.parcelOrder.value.receiverPickupDateTime != null // ? "Delivery Time: ${controller.formatDate(controller.parcelOrder.value.receiverPickupDateTime!)}" // : '', @@ -125,16 +195,42 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - _iconTile("${controller.parcelOrder.value.distance ?? '--'} ${'KM'.tr()}", "Distance".tr(), "assets/icons/ic_distance_parcel.svg", isDark), - _iconTile(controller.parcelOrder.value.parcelWeight ?? '--', "Weight".tr(), "assets/icons/ic_weight_parcel.svg", isDark), - _iconTile(Constant.amountShow(amount: controller.parcelOrder.value.subTotal), "Rate".tr(), "assets/icons/ic_rate_parcel.svg", isDark), + _iconTile( + "${controller.parcelOrder.value.distance ?? '--'} ${'KM'.tr()}", + "Distance".tr(), + "assets/icons/ic_distance_parcel.svg", + isDark, + ), + _iconTile( + controller.parcelOrder.value.parcelWeight ?? + '--', + "Weight".tr(), + "assets/icons/ic_weight_parcel.svg", + isDark, + ), + _iconTile( + Constant.amountShow( + amount: controller.parcelOrder.value.subTotal, + ), + "Rate".tr(), + "assets/icons/ic_rate_parcel.svg", + isDark, + ), ], ), ), @@ -143,24 +239,53 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Row( children: [ - Expanded(child: Text("Coupons".tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Expanded( + child: Text( + "Coupons".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), InkWell( onTap: () { Get.to(ParcelCouponScreen())!.then((value) { if (value != null) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: value); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = value; + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: value, + ); + if (couponAmount < + controller.subTotal.value) { + controller.selectedCouponModel.value = + value; controller.calculatePrice(); } else { - ShowToastDialog.showToast("This offer not eligible for this booking".tr()); + ShowToastDialog.showToast( + "This offer not eligible for this booking" + .tr(), + ); } } }); }, child: Text( "View All".tr(), - style: AppThemeData.boldTextStyle(decoration: TextDecoration.underline, fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.boldTextStyle( + decoration: TextDecoration.underline, + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ], @@ -169,21 +294,45 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { // Coupon input DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: isDark ? AppThemeData.parcelServiceDark300 : AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(10), + color: + isDark + ? AppThemeData.parcelServiceDark300 + : AppThemeData.primary300, + ), child: Container( - decoration: BoxDecoration(color: AppThemeData.parcelService50, borderRadius: BorderRadius.circular(10)), - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: AppThemeData.parcelService50, + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_coupon_parcel.svg", height: 28, width: 28), + SvgPicture.asset( + "assets/icons/ic_coupon_parcel.svg", + height: 28, + width: 28, + ), SizedBox(width: 15), Expanded( child: TextField( - controller: controller.couponController.value, - style: AppThemeData.semiBoldTextStyle(color: AppThemeData.parcelService500, fontSize: 16), + controller: + controller.couponController.value, + style: AppThemeData.semiBoldTextStyle( + color: AppThemeData.parcelService500, + fontSize: 16, + ), decoration: InputDecoration( hintText: "Write coupon code".tr(), - hintStyle: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.parcelService500), + hintStyle: AppThemeData.mediumTextStyle( + fontSize: 16, + color: AppThemeData.parcelService500, + ), border: InputBorder.none, ), ), @@ -191,22 +340,60 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { RoundedButtonFill( title: "Redeem now".tr(), onPress: () { - if (controller.couponList.where((element) => element.code!.toLowerCase() == controller.couponController.value.text.toLowerCase()).isNotEmpty) { - CouponModel couponModel = controller.couponList.firstWhere((p0) => p0.code!.toLowerCase() == controller.couponController.value.text.toLowerCase()); - if (couponModel.expiresAt!.toDate().isAfter(DateTime.now())) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: couponModel); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = couponModel; + if (controller.couponList + .where( + (element) => + element.code!.toLowerCase() == + controller + .couponController + .value + .text + .toLowerCase(), + ) + .isNotEmpty) { + CouponModel couponModel = controller + .couponList + .firstWhere( + (p0) => + p0.code!.toLowerCase() == + controller + .couponController + .value + .text + .toLowerCase(), + ); + if (couponModel.expiresAt! + .toDate() + .isAfter(DateTime.now())) { + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: couponModel, + ); + if (couponAmount < + controller.subTotal.value) { + controller.selectedCouponModel.value = + couponModel; controller.calculatePrice(); controller.update(); } else { - ShowToastDialog.showToast("This offer not eligible for this booking".tr()); + ShowToastDialog.showToast( + "This offer not eligible for this booking" + .tr(), + ); } } else { - ShowToastDialog.showToast("This coupon code has been expired".tr()); + ShowToastDialog.showToast( + "This coupon code has been expired" + .tr(), + ); } } else { - ShowToastDialog.showToast("Invalid coupon code".tr()); + ShowToastDialog.showToast( + "Invalid coupon code".tr(), + ); } }, borderRadius: 10, @@ -224,35 +411,84 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Order Summary".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500)), + Text( + "Order Summary".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey500, + ), + ), const SizedBox(height: 8), // Subtotal - _summaryTile("Subtotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark, null), + _summaryTile( + "Subtotal".tr(), + Constant.amountShow( + amount: controller.subTotal.value.toString(), + ), + isDark, + null, + ), // Discount - _summaryTile("Discount".tr(), "-${Constant.amountShow(amount: controller.discount.value.toString())}", isDark, AppThemeData.dangerDark300), + _summaryTile( + "Discount".tr(), + "-${Constant.amountShow(amount: controller.discount.value.toString())}", + isDark, + AppThemeData.dangerDark300, + ), // Tax List - ...List.generate(Constant.taxList.length, (index) { + ...List.generate(Constant.taxList.length, ( + index, + ) { final taxModel = Constant.taxList[index]; - final taxTitle = "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; - final taxAmount = Constant.getTaxValue(amount: (controller.subTotal.value - controller.discount.value).toString(), taxModel: taxModel).toString(); + final taxTitle = + "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; + final taxAmount = + Constant.getTaxValue( + amount: + (controller.subTotal.value - + controller.discount.value) + .toString(), + taxModel: taxModel, + ).toString(); - return _summaryTile(taxTitle, Constant.amountShow(amount: taxAmount), isDark, null); + return _summaryTile( + taxTitle, + Constant.amountShow(amount: taxAmount), + isDark, + null, + ); }), const Divider(), // Total - _summaryTile("Order Total".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark, null), + _summaryTile( + "Order Total".tr(), + Constant.amountShow( + amount: + controller.totalAmount.value.toString(), + ), + isDark, + null, + ), ], ), ), @@ -260,15 +496,32 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title - Text("Payment by".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Payment by".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 12), // Row with Sender and Receiver options @@ -276,16 +529,36 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { children: [ // Sender GestureDetector( - onTap: () => controller.paymentBy.value = "Sender", + onTap: + () => + controller.paymentBy.value = + "Sender", child: Row( children: [ Icon( - controller.paymentBy.value == "Sender" ? Icons.radio_button_checked : Icons.radio_button_off, - color: controller.paymentBy.value == "Sender" ? AppThemeData.primary300 : (isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + controller.paymentBy.value == "Sender" + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: + controller.paymentBy.value == + "Sender" + ? AppThemeData.primary300 + : (isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500), size: 20, ), const SizedBox(width: 6), - Text("Sender".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + "Sender".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), + ), ], ), ), @@ -294,16 +567,37 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { // Receiver GestureDetector( - onTap: () => controller.paymentBy.value = "Receiver", + onTap: + () => + controller.paymentBy.value = + "Receiver", child: Row( children: [ Icon( - controller.paymentBy.value == "Receiver" ? Icons.radio_button_checked : Icons.radio_button_off, - color: controller.paymentBy.value == "Receiver" ? AppThemeData.primary300 : (isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + controller.paymentBy.value == + "Receiver" + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: + controller.paymentBy.value == + "Receiver" + ? AppThemeData.primary300 + : (isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500), size: 20, ), const SizedBox(width: 6), - Text("Receiver".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + "Receiver".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), + ), ], ), ), @@ -317,13 +611,23 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { // Continue button RoundedButtonFill( - title: controller.paymentBy.value == "Sender" ? "Select Payment Method".tr() : "Continue".tr(), + title: + controller.paymentBy.value == "Sender" + ? "Select Payment Method".tr() + : "Continue".tr(), onPress: () async { if (controller.paymentBy.value == "Sender") { Get.bottomSheet( - paymentBottomSheet(context, controller, isDark), // your widget - isScrollControlled: true, // ✅ allows full drag scrolling - backgroundColor: Colors.transparent, // so your rounded corners are visible + paymentBottomSheet( + context, + controller, + isDark, + ), // your widget + isScrollControlled: + true, // ✅ allows full drag scrolling + backgroundColor: + Colors + .transparent, // so your rounded corners are visible ); } else { controller.placeOrder(); @@ -340,14 +644,44 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { ); } - Widget _infoSection(String title, String name, String address, String phone, bool isDark) { + Widget _infoSection( + String title, + String name, + String address, + String phone, + bool isDark, + ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + name, + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + address, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + phone, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), // Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ], ); @@ -357,11 +691,28 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { return Column( children: [ // Icon(icon, color: AppThemeData.primary300), - SvgPicture.asset(icon, height: 28, width: 28, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800), + SvgPicture.asset( + icon, + height: 28, + width: 28, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), const SizedBox(height: 6), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), const SizedBox(height: 6), - Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ); } @@ -372,14 +723,32 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: title == "Order Total" ? 18 : 16, color: colors ?? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Text( + title, + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: title == "Order Total" ? 18 : 16, + color: + colors ?? + (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ), + ), ], ), ); } - Widget paymentBottomSheet(BuildContext context, ParcelOrderConfirmationController controller, bool isDark) { + Widget paymentBottomSheet( + BuildContext context, + ParcelOrderConfirmationController controller, + bool isDark, + ) { return DraggableScrollableSheet( initialChildSize: 0.70, minChildSize: 0.30, @@ -388,14 +757,26 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey500 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey500 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Select Payment Method".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Select Payment Method".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), GestureDetector( onTap: () { Get.back(); @@ -409,63 +790,213 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { child: ListView( controller: scrollController, children: [ - Text("Preferred Payment".tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Preferred Payment".tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) const SizedBox(height: 10), - Text("Other Payment Options".tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) + const SizedBox(height: 10), + Text( + "Other Payment Options".tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -479,25 +1010,59 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { color: AppThemeData.taxiBooking300, textColor: AppThemeData.grey900, onPress: () async { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.totalAmount.value.toString(), context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.totalAmount.value.toString(), + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.cod.name) { controller.placeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { - double walletBalance = double.tryParse(controller.userModel.value.walletAmount.toString()) ?? 0.0; - double amountToPay = double.tryParse(controller.totalAmount.value.toString()) ?? 0.0; + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name) { + double walletBalance = + double.tryParse( + controller.userModel.value.walletAmount.toString(), + ) ?? + 0.0; + double amountToPay = + double.tryParse( + controller.totalAmount.value.toString(), + ) ?? + 0.0; if (walletBalance < amountToPay) { - ShowToastDialog.showToast("Insufficient wallet balance".tr()); + ShowToastDialog.showToast( + "Insufficient wallet balance".tr(), + ); return; } controller.placeOrder(); @@ -505,24 +1070,52 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { // else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { // controller.placeOrder(); // } - else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.totalAmount.value.toString()), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.totalAmount.value.toString(), orderId: result.id); - } - }); + else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.totalAmount.value.toString(), + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: controller.totalAmount.value.toString(), + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } }, ), @@ -546,8 +1139,16 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -558,12 +1159,30 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: Constant.userModel?.walletAmount == null ? '0.0' : Constant.userModel?.walletAmount.toString()), + Constant.amountShow( + amount: + Constant.userModel?.walletAmount == null + ? '0.0' + : Constant.userModel?.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -572,13 +1191,18 @@ class ParcelOrderConfirmationScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark ? AppThemeData.grey50 : AppThemeData.grey900, + ), ), ), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/parcel_service/parcel_order_details.dart b/lib/screen_ui/parcel_service/parcel_order_details.dart index 8c75859..9a801bd 100644 --- a/lib/screen_ui/parcel_service/parcel_order_details.dart +++ b/lib/screen_ui/parcel_service/parcel_order_details.dart @@ -3,7 +3,7 @@ import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/parcel_order_details_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -40,8 +40,20 @@ class ParcelOrderDetails extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -49,12 +61,22 @@ class ParcelOrderDetails extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Order Details".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), Text( - "Your parcel is on the way. Track it in real time below.".tr(), + "Order Details".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + Text( + "Your parcel is on the way. Track it in real time below." + .tr(), maxLines: 1, overflow: TextOverflow.ellipsis, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.grey900), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), ), ], ), @@ -74,23 +96,47 @@ class ParcelOrderDetails extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), width: double.infinity, padding: const EdgeInsets.all(16), child: Text( - "${'Order Id:'.tr()} ${Constant.orderId(orderId: controller.parcelOrder.value.id.toString())}".tr(), + "${'Order Id:'.tr()} ${Constant.orderId(orderId: controller.parcelOrder.value.id.toString())}" + .tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 18, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 18, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const SizedBox(height: 16), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( @@ -102,7 +148,11 @@ class ParcelOrderDetails extends StatelessWidget { // Timeline with icons and line Column( children: [ - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, + ), DottedBorder( options: CustomPathDottedBorderOptions( color: Colors.grey.shade400, @@ -112,24 +162,50 @@ class ParcelOrderDetails extends StatelessWidget { (size) => Path() ..moveTo(size.width / 2, 0) - ..lineTo(size.width / 2, size.height), + ..lineTo( + size.width / 2, + size.height, + ), + ), + child: const SizedBox( + width: 20, + height: 95, ), - child: const SizedBox(width: 20, height: 95), ), - Image.asset("assets/images/image_parcel.png", height: 32, width: 32), + Image.asset( + "assets/images/image_parcel.png", + height: 32, + width: 32, + ), ], ), const SizedBox(width: 12), // Address Details Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ _infoSection( "Pickup Address (Sender):".tr(), - controller.parcelOrder.value.sender?.name ?? '', - controller.parcelOrder.value.sender?.address ?? '', - controller.parcelOrder.value.sender?.phone ?? '', + controller + .parcelOrder + .value + .sender + ?.name ?? + '', + controller + .parcelOrder + .value + .sender + ?.address ?? + '', + controller + .parcelOrder + .value + .sender + ?.phone ?? + '', // controller.parcelOrder.value.senderPickupDateTime != null // ? "Pickup Time: ${controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}" // : '', @@ -138,9 +214,24 @@ class ParcelOrderDetails extends StatelessWidget { const SizedBox(height: 16), _infoSection( "Delivery Address (Receiver):".tr(), - controller.parcelOrder.value.receiver?.name ?? '', - controller.parcelOrder.value.receiver?.address ?? '', - controller.parcelOrder.value.receiver?.phone ?? '', + controller + .parcelOrder + .value + .receiver + ?.name ?? + '', + controller + .parcelOrder + .value + .receiver + ?.address ?? + '', + controller + .parcelOrder + .value + .receiver + ?.phone ?? + '', // controller.parcelOrder.value.receiverPickupDateTime != null // ? "Delivery Time: ${controller.formatDate(controller.parcelOrder.value.receiverPickupDateTime!)}" // : '', @@ -154,12 +245,16 @@ class ParcelOrderDetails extends StatelessWidget { const Divider(), - if (controller.parcelOrder.value.isSchedule == true) + if (controller.parcelOrder.value.isSchedule == + true) Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Text( "${'Schedule Pickup time:'.tr()} ${controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.info400, + ), ), ), @@ -167,23 +262,61 @@ class ParcelOrderDetails extends StatelessWidget { padding: const EdgeInsets.only(bottom: 8.0), child: Text( "${'Order Date:'.tr()}${controller.parcelOrder.value.isSchedule == true ? controller.formatDate(controller.parcelOrder.value.createdAt!) : controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.info400, + ), ), ), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - Text("Parcel Type:".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + "Parcel Type:".tr(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), + ), Row( children: [ Text( - controller.parcelOrder.value.parcelType ?? '', - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800), + controller + .parcelOrder + .value + .parcelType ?? + '', + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark800 + : AppThemeData.grey800, + ), ), const SizedBox(width: 8), - if (controller.getSelectedCategory()?.image != null && controller.getSelectedCategory()!.image!.isNotEmpty) - NetworkImageWidget(imageUrl: controller.getSelectedCategory()?.image ?? '', height: 20, width: 20), + if (controller + .getSelectedCategory() + ?.image != + null && + controller + .getSelectedCategory()! + .image! + .isNotEmpty) + NetworkImageWidget( + imageUrl: + controller + .getSelectedCategory() + ?.image ?? + '', + height: 20, + width: 20, + ), ], ), ], @@ -193,15 +326,31 @@ class ParcelOrderDetails extends StatelessWidget { : SizedBox( height: 120, child: ListView.builder( - itemCount: controller.parcelOrder.value.parcelImages!.length, + itemCount: + controller + .parcelOrder + .value + .parcelImages! + .length, shrinkWrap: true, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: NetworkImageWidget(imageUrl: controller.parcelOrder.value.parcelImages![index], width: 100, fit: BoxFit.cover, borderRadius: 10), + borderRadius: BorderRadius.circular( + 10, + ), + child: NetworkImageWidget( + imageUrl: + controller + .parcelOrder + .value + .parcelImages![index], + width: 100, + fit: BoxFit.cover, + borderRadius: 10, + ), ), ); }, @@ -215,16 +364,42 @@ class ParcelOrderDetails extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - _iconTile("${controller.parcelOrder.value.distance ?? '--'} ${Constant.distanceType}", "Distance".tr(), "assets/icons/ic_distance_parcel.svg", isDark), - _iconTile(controller.parcelOrder.value.parcelWeight ?? '--', "Weight".tr(), "assets/icons/ic_weight_parcel.svg", isDark), - _iconTile(Constant.amountShow(amount: controller.parcelOrder.value.subTotal), "Rate".tr(), "assets/icons/ic_rate_parcel.svg", isDark), + _iconTile( + "${controller.parcelOrder.value.distance ?? '--'} ${Constant.distanceType}", + "Distance".tr(), + "assets/icons/ic_distance_parcel.svg", + isDark, + ), + _iconTile( + controller.parcelOrder.value.parcelWeight ?? + '--', + "Weight".tr(), + "assets/icons/ic_weight_parcel.svg", + isDark, + ), + _iconTile( + Constant.amountShow( + amount: controller.parcelOrder.value.subTotal, + ), + "Rate".tr(), + "assets/icons/ic_rate_parcel.svg", + isDark, + ), ], ), ), @@ -235,18 +410,37 @@ class ParcelOrderDetails extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("About Driver".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "About Driver".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 8), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Row( children: [ @@ -254,19 +448,48 @@ class ParcelOrderDetails extends StatelessWidget { width: 52, height: 52, child: ClipRRect( - borderRadius: BorderRadiusGeometry.circular(10), - child: NetworkImageWidget(imageUrl: controller.driverUser.value?.profilePictureURL ?? '', height: 70, width: 70, borderRadius: 35), + borderRadius: + BorderRadiusGeometry.circular( + 10, + ), + child: NetworkImageWidget( + imageUrl: + controller + .driverUser + .value + ?.profilePictureURL ?? + '', + height: 70, + width: 70, + borderRadius: 35, + ), ), ), SizedBox(width: 20), Text( - controller.parcelOrder.value.driver?.fullName() ?? '', - style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18), + controller + .parcelOrder + .value + .driver + ?.fullName() ?? + '', + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData.grey900, + fontSize: 18, + ), ), ], ), RoundedButtonBorder( - title: controller.driverUser.value!.averageRating.toStringAsFixed(1), + title: controller + .driverUser + .value! + .averageRating + .toStringAsFixed(1), width: 20, height: 3.5, radius: 10, @@ -275,72 +498,155 @@ class ParcelOrderDetails extends StatelessWidget { textColor: AppThemeData.warning400, borderColor: AppThemeData.warning400, color: AppThemeData.warning50, - icon: SvgPicture.asset("assets/icons/ic_start.svg"), + icon: SvgPicture.asset( + "assets/icons/ic_start.svg", + ), onPress: () {}, ), ], ), Visibility( - visible: controller.parcelOrder.value.status == Constant.orderCompleted ? true : false, + visible: + controller.parcelOrder.value.status == + Constant.orderCompleted + ? true + : false, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: RoundedButtonFill( - title: controller.ratingModel.value.id != null && controller.ratingModel.value.id!.isNotEmpty ? 'Update Review'.tr() : 'Add Review'.tr(), + title: + controller.ratingModel.value.id != + null && + controller + .ratingModel + .value + .id! + .isNotEmpty + ? 'Update Review'.tr() + : 'Add Review'.tr(), onPress: () async { - final result = await Get.to(() => ParcelReviewScreen(), arguments: {'order': controller.parcelOrder.value}); + final result = await Get.to( + () => ParcelReviewScreen(), + arguments: { + 'order': + controller + .parcelOrder + .value, + }, + ); // If review was submitted successfully if (result == true) { - await controller.fetchDriverDetails(); + await controller + .fetchDriverDetails(); } }, height: 5, borderRadius: 15, color: Colors.orange, - textColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + textColor: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, ), ), ), - if (controller.parcelOrder.value.status != Constant.orderCompleted) + if (controller.parcelOrder.value.status != + Constant.orderCompleted) Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ InkWell( onTap: () { - Constant.makePhoneCall(controller.parcelOrder.value.driver!.phoneNumber.toString()); + Constant.makePhoneCall( + controller + .parcelOrder + .value + .driver! + .phoneNumber + .toString(), + ); }, child: Container( width: 150, height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_phone_call.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_phone_call.svg")), ), ), const SizedBox(width: 10), InkWell( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); - UserModel? customer = await FireStoreUtils.getUserProfile(controller.parcelOrder.value.authorID ?? ''); - UserModel? driverUser = await FireStoreUtils.getUserProfile(controller.parcelOrder.value.driverId ?? ''); + UserModel? customer = + await FireStoreUtils.getUserProfile( + controller + .parcelOrder + .value + .authorID ?? + '', + ); + UserModel? driverUser = + await FireStoreUtils.getUserProfile( + controller + .parcelOrder + .value + .driverId ?? + '', + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": customer?.fullName(), - "restaurantName": driverUser?.fullName(), - "orderId": controller.parcelOrder.value.id, - "restaurantId": driverUser?.id, + "customerName": + customer?.fullName(), + "restaurantName": + driverUser?.fullName(), + "orderId": + controller + .parcelOrder + .value + .id, + "restaurantId": + driverUser?.id, "customerId": customer?.id, - "customerProfileImage": customer?.profilePictureURL, - "restaurantProfileImage": driverUser?.profilePictureURL, + "customerProfileImage": + customer + ?.profilePictureURL, + "restaurantProfileImage": + driverUser + ?.profilePictureURL, "token": driverUser?.fcmToken, "chatType": "Driver", }, @@ -351,11 +657,29 @@ class ParcelOrderDetails extends StatelessWidget { height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_wechat.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_wechat.svg")), ), ), ], @@ -369,43 +693,98 @@ class ParcelOrderDetails extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Order Summary".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500)), + Text( + "Order Summary".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey500, + ), + ), const SizedBox(height: 8), // Subtotal - _summaryTile("Subtotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark), + _summaryTile( + "Subtotal".tr(), + Constant.amountShow( + amount: controller.subTotal.value.toString(), + ), + isDark, + ), // Discount - _summaryTile("Discount".tr(), Constant.amountShow(amount: controller.discount.value.toString()), isDark), + _summaryTile( + "Discount".tr(), + Constant.amountShow( + amount: controller.discount.value.toString(), + ), + isDark, + ), // Tax List - ...List.generate(controller.parcelOrder.value.taxSetting!.length, (index) { - return _summaryTile( - "${controller.parcelOrder.value.taxSetting![index].title} ${controller.parcelOrder.value.taxSetting![index].type == 'fix' ? '' : '(${controller.parcelOrder.value.taxSetting![index].tax}%)'}", - Constant.amountShow( - amount: - Constant.getTaxValue( - amount: - ((double.tryParse(controller.parcelOrder.value.subTotal.toString()) ?? 0.0) - (double.tryParse(controller.parcelOrder.value.discount.toString()) ?? 0.0)) - .toString(), - taxModel: controller.parcelOrder.value.taxSetting![index], - ).toString(), - ), - isDark, - ); - }), + ...List.generate( + controller.parcelOrder.value.taxSetting!.length, + (index) { + return _summaryTile( + "${controller.parcelOrder.value.taxSetting![index].title} ${controller.parcelOrder.value.taxSetting![index].type == 'fix' ? '' : '(${controller.parcelOrder.value.taxSetting![index].tax}%)'}", + Constant.amountShow( + amount: + Constant.getTaxValue( + amount: + ((double.tryParse( + controller + .parcelOrder + .value + .subTotal + .toString(), + ) ?? + 0.0) - + (double.tryParse( + controller + .parcelOrder + .value + .discount + .toString(), + ) ?? + 0.0)) + .toString(), + taxModel: + controller + .parcelOrder + .value + .taxSetting![index], + ).toString(), + ), + isDark, + ); + }, + ), const Divider(), // Total - _summaryTile("Order Total".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark), + _summaryTile( + "Order Total".tr(), + Constant.amountShow( + amount: + controller.totalAmount.value.toString(), + ), + isDark, + ), ], ), ), @@ -424,7 +803,10 @@ class ParcelOrderDetails extends StatelessWidget { height: 5, borderRadius: 15, color: AppThemeData.primary300, - textColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + textColor: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, ), ) : SizedBox(), @@ -433,7 +815,11 @@ class ParcelOrderDetails extends StatelessWidget { ); } - Widget statusBottomSheet(BuildContext context, ParcelOrderDetailsController controller, bool isDark) { + Widget statusBottomSheet( + BuildContext context, + ParcelOrderDetailsController controller, + bool isDark, + ) { return DraggableScrollableSheet( initialChildSize: 0.30, minChildSize: 0.20, @@ -442,23 +828,46 @@ class ParcelOrderDetails extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey500 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey500 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), child: SingleChildScrollView( controller: scrollController, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Parcel Status Timeline".tr(), style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18)), + Text( + "Parcel Status Timeline".tr(), + style: AppThemeData.semiBoldTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + fontSize: 18, + ), + ), const SizedBox(height: 8), // Dynamic List Obx(() { - final history = controller.parcelOrder.value.statusHistory ?? []; + final history = + controller.parcelOrder.value.statusHistory ?? []; if (history.isEmpty) { return SizedBox( height: 80, - child: Center(child: Text("No status updates yet".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + child: Center( + child: Text( + "No status updates yet".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), ); } @@ -476,12 +885,26 @@ class ParcelOrderDetails extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Image.asset(isCompleted ? "assets/images/image_status_timeline.png" : "assets/images/image_timeline.png", height: 48, width: 48), + Image.asset( + isCompleted + ? "assets/images/image_status_timeline.png" + : "assets/images/image_timeline.png", + height: 48, + width: 48, + ), const SizedBox(width: 20), Expanded( child: Text( statusUpdate.status ?? '', - style: AppThemeData.semiBoldTextStyle(color: isCompleted ? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900) : AppThemeData.grey500, fontSize: 18), + style: AppThemeData.semiBoldTextStyle( + color: + isCompleted + ? (isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900) + : AppThemeData.grey500, + fontSize: 18, + ), ), ), ], @@ -499,14 +922,44 @@ class ParcelOrderDetails extends StatelessWidget { ); } - Widget _infoSection(String title, String name, String address, String phone, bool isDark) { + Widget _infoSection( + String title, + String name, + String address, + String phone, + bool isDark, + ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + name, + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + address, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), + Text( + phone, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), // Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ], ); @@ -516,11 +969,28 @@ class ParcelOrderDetails extends StatelessWidget { return Column( children: [ // Icon(icon, color: AppThemeData.primary300), - SvgPicture.asset(icon, height: 28, width: 28, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800), + SvgPicture.asset( + icon, + height: 28, + width: 28, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), const SizedBox(height: 6), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), const SizedBox(height: 6), - Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ); } @@ -531,8 +1001,20 @@ class ParcelOrderDetails extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: title == "Order Total".tr() ? 18 : 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + title, + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: title == "Order Total".tr() ? 18 : 16, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), ], ), ); diff --git a/lib/screen_ui/parcel_service/parcel_review_screen.dart b/lib/screen_ui/parcel_service/parcel_review_screen.dart index 3464b07..8a829c4 100644 --- a/lib/screen_ui/parcel_service/parcel_review_screen.dart +++ b/lib/screen_ui/parcel_service/parcel_review_screen.dart @@ -2,7 +2,7 @@ import 'package:customer/controllers/parcel_review_controller.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; @@ -26,10 +26,22 @@ class ParcelReviewScreen extends StatelessWidget { centerTitle: true, elevation: 0, backgroundColor: AppThemeData.primary300, - leading: GestureDetector(onTap: () => Get.back(), child: Icon(Icons.arrow_back_ios, color: isDark ? Colors.white : Colors.black)), + leading: GestureDetector( + onTap: () => Get.back(), + child: Icon( + Icons.arrow_back_ios, + color: isDark ? Colors.white : Colors.black, + ), + ), title: Text( - controller.ratingModel.value != null && controller.ratingModel.value!.id!.isNotEmpty ? "Update Review".tr() : "Add Review".tr(), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 16), + controller.ratingModel.value != null && + controller.ratingModel.value!.id!.isNotEmpty + ? "Update Review".tr() + : "Add Review".tr(), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontSize: 16, + ), ), ), body: Obx( @@ -41,11 +53,21 @@ class ParcelReviewScreen extends StatelessWidget { child: Stack( children: [ Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 50, bottom: 20), + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 50, + bottom: 20, + ), child: Card( elevation: 2, - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(top: 65), @@ -53,65 +75,148 @@ class ParcelReviewScreen extends StatelessWidget { children: [ // Driver Name Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only( + top: 8.0, + ), child: Text( - controller.order.value!.driver?.fullName() ?? "", - style: TextStyle(color: isDark ? Colors.white : Colors.black87, fontFamily: AppThemeData.medium, fontSize: 18), + controller.order.value!.driver + ?.fullName() ?? + "", + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black87, + fontFamily: AppThemeData.medium, + fontSize: 18, + ), ), ), // Car info - const Padding(padding: EdgeInsets.symmetric(vertical: 12), child: Divider(color: Colors.grey)), + const Padding( + padding: EdgeInsets.symmetric( + vertical: 12, + ), + child: Divider(color: Colors.grey), + ), // Title Padding( padding: const EdgeInsets.only(top: 16), - child: Text('How is your trip?'.tr(), style: TextStyle(fontSize: 18, color: isDark ? Colors.white : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 2)), + child: Text( + 'How is your trip?'.tr(), + style: TextStyle( + fontSize: 18, + color: + isDark + ? Colors.white + : Colors.black, + fontWeight: FontWeight.bold, + letterSpacing: 2, + ), + ), ), Padding( padding: const EdgeInsets.only(top: 8), child: Text( - 'Your feedback will help us improve \n driving experience better'.tr(), + 'Your feedback will help us improve \n driving experience better' + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8), + style: TextStyle( + color: + isDark + ? Colors.white + : Colors.black.withOpacity( + 0.60, + ), + letterSpacing: 0.8, + ), ), ), // Rating Padding( padding: const EdgeInsets.only(top: 20), - child: Text('Rate for'.tr(), style: TextStyle(fontSize: 16, color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8)), + child: Text( + 'Rate for'.tr(), + style: TextStyle( + fontSize: 16, + color: + isDark + ? Colors.white + : Colors.black.withOpacity( + 0.60, + ), + letterSpacing: 0.8, + ), + ), ), Padding( padding: const EdgeInsets.only(top: 8), child: Text( - controller.order.value!.driver?.fullName() ?? "", - style: TextStyle(fontSize: 18, color: isDark ? Colors.white : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 2), + controller.order.value!.driver + ?.fullName() ?? + "", + style: TextStyle( + fontSize: 18, + color: + isDark + ? Colors.white + : Colors.black, + fontWeight: FontWeight.bold, + letterSpacing: 2, + ), ), ), Padding( padding: const EdgeInsets.only(top: 10), child: RatingBar.builder( - initialRating: controller.ratings.value, + initialRating: + controller.ratings.value, minRating: 1, direction: Axis.horizontal, allowHalfRating: true, itemCount: 5, - itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber), - unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, - onRatingUpdate: (rating) => controller.ratings.value = rating, + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: Colors.amber, + ), + unratedColor: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey400, + onRatingUpdate: + (rating) => + controller.ratings.value = + rating, ), ), // Comment - Padding(padding: const EdgeInsets.all(20.0), child: TextFieldWidget(hintText: "Type comment....".tr(), controller: controller.comment.value, maxLine: 5)), + Padding( + padding: const EdgeInsets.all(20.0), + child: TextFieldWidget( + hintText: "Type comment....".tr(), + controller: controller.comment.value, + maxLine: 5, + ), + ), // Submit Button Padding( padding: const EdgeInsets.all(20.0), child: RoundedButtonFill( - title: controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(), + title: + controller.ratingModel.value != + null + ? "Update Review".tr() + : "Add Review".tr(), color: AppThemeData.primary300, - textColor: isDark ? Colors.white : Colors.black, + textColor: + isDark + ? Colors.white + : Colors.black, onPress: controller.submitReview, ), ), @@ -127,11 +232,28 @@ class ParcelReviewScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(60), color: Colors.white, - boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.15), blurRadius: 8, spreadRadius: 6)], + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.15), + blurRadius: 8, + spreadRadius: 6, + ), + ], ), child: ClipRRect( borderRadius: BorderRadius.circular(60), - child: NetworkImageWidget(imageUrl: controller.order.value?.driver?.profilePictureURL ?? '', fit: BoxFit.cover, height: 110, width: 110), + child: NetworkImageWidget( + imageUrl: + controller + .order + .value + ?.driver + ?.profilePictureURL ?? + '', + fit: BoxFit.cover, + height: 110, + width: 110, + ), ), ), ), diff --git a/lib/screen_ui/rental_service/my_rental_booking_screen.dart b/lib/screen_ui/rental_service/my_rental_booking_screen.dart index 072d05a..11c5f77 100644 --- a/lib/screen_ui/rental_service/my_rental_booking_screen.dart +++ b/lib/screen_ui/rental_service/my_rental_booking_screen.dart @@ -6,7 +6,7 @@ import 'package:customer/screen_ui/rental_service/rental_order_details_screen.da import 'package:customer/themes/round_button_fill.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/my_rental_booking_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -25,14 +25,27 @@ class MyRentalBookingScreen extends StatelessWidget { builder: (controller) { return DefaultTabController( length: controller.tabTitles.length, - initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value), + initialIndex: controller.tabTitles.indexOf( + controller.selectedTab.value, + ), child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: AppThemeData.primary300, title: Padding( padding: const EdgeInsets.only(bottom: 10), - child: Row(children: [const SizedBox(width: 10), Text("Rental History".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900))]), + child: Row( + children: [ + const SizedBox(width: 10), + Text( + "Rental History".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), + ], + ), ), bottom: TabBar( onTap: (index) { @@ -42,8 +55,13 @@ class MyRentalBookingScreen extends StatelessWidget { labelColor: AppThemeData.parcelService500, unselectedLabelColor: AppThemeData.parcelService500, labelStyle: AppThemeData.boldTextStyle(fontSize: 13), - unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 13), - tabs: controller.tabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(), + unselectedLabelStyle: AppThemeData.mediumTextStyle( + fontSize: 13, + ), + tabs: + controller.tabTitles + .map((title) => Tab(child: Center(child: Text(title)))) + .toList(), ), ), body: @@ -56,12 +74,30 @@ class MyRentalBookingScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)), + Text( + "Please Log In to Continue".tr(), + style: TextStyle( + color: + isDark + ? AppThemeData.grey100 + : AppThemeData.grey800, + fontSize: 22, + fontFamily: AppThemeData.semiBold, + ), + ), const SizedBox(height: 5), Text( - "You’re not logged in. Please sign in to access your account and explore all features.".tr(), + "You’re not logged in. Please sign in to access your account and explore all features." + .tr(), textAlign: TextAlign.center, - style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold), + style: TextStyle( + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey500, + fontSize: 16, + fontFamily: AppThemeData.bold, + ), ), const SizedBox(height: 20), RoundedButtonFill( @@ -80,71 +116,154 @@ class MyRentalBookingScreen extends StatelessWidget { : TabBarView( children: controller.tabTitles.map((title) { - List orders = controller.getOrdersForTab(title); + List orders = controller + .getOrdersForTab(title); if (orders.isEmpty) { - return Center(child: Text("No orders found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))); + return Center( + child: Text( + "No orders found".tr(), + style: AppThemeData.mediumTextStyle( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: orders.length, itemBuilder: (context, index) { - RentalOrderModel order = orders[index]; //use this + RentalOrderModel order = + orders[index]; //use this return InkWell( onTap: () { - Get.to(() => RentalOrderDetailsScreen(), arguments: order); + Get.to( + () => RentalOrderDetailsScreen(), + arguments: order, + ); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), margin: const EdgeInsets.only(bottom: 10), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Padding(padding: const EdgeInsets.only(top: 5), child: Image.asset("assets/icons/pickup.png", height: 18, width: 18)), + Padding( + padding: const EdgeInsets.only( + top: 5, + ), + child: Image.asset( + "assets/icons/pickup.png", + height: 18, + width: 18, + ), + ), const SizedBox(width: 10), Expanded( //prevents overflow child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Expanded( //text wraps if too long child: Text( - order.sourceLocationName ?? "-", - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), - overflow: TextOverflow.ellipsis, //safe cutoff + order.sourceLocationName ?? + "-", + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), + overflow: + TextOverflow + .ellipsis, //safe cutoff maxLines: 2, ), ), - if (order.status != null) ...[ - const SizedBox(width: 8), + if (order.status != + null) ...[ + const SizedBox( + width: 8, + ), Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), + padding: + const EdgeInsets.symmetric( + vertical: 6, + horizontal: 12, + ), decoration: BoxDecoration( - color: AppThemeData.info50, - border: Border.all(color: AppThemeData.info300), - borderRadius: BorderRadius.circular(12), + color: + AppThemeData + .info50, + border: Border.all( + color: + AppThemeData + .info300, + ), + borderRadius: + BorderRadius.circular( + 12, + ), + ), + child: Text( + order.status ?? '', + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + AppThemeData + .info500, + ), ), - child: Text(order.status ?? '', style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)), ), ], ], ), - if (order.bookingDateTime != null) + if (order.bookingDateTime != + null) Text( - Constant.timestampToDateTime(order.bookingDateTime!), - style: AppThemeData.mediumTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + Constant.timestampToDateTime( + order.bookingDateTime!, + ), + style: AppThemeData.mediumTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ], ), @@ -152,41 +271,112 @@ class MyRentalBookingScreen extends StatelessWidget { ], ), const SizedBox(height: 12), - Text("Vehicle Type :".tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Vehicle Type :".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), child: Row( children: [ ClipRRect( //borderRadius: BorderRadius.circular(10), child: CachedNetworkImage( - imageUrl: order.rentalVehicleType!.rentalVehicleIcon.toString(), + imageUrl: + order + .rentalVehicleType! + .rentalVehicleIcon + .toString(), height: 60, width: 60, imageBuilder: - (context, imageProvider) => Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover)), + ( + context, + imageProvider, + ) => Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 10, + ), + image: DecorationImage( + image: + imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), + errorWidget: + ( + context, + url, + error, + ) => Image.network( + Constant + .placeHolderImage, + fit: BoxFit.cover, ), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), fit: BoxFit.cover, ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( "${order.rentalVehicleType!.name}", - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), Padding( - padding: const EdgeInsets.only(top: 2.0), + padding: + const EdgeInsets.only( + top: 2.0, + ), child: Text( "${order.rentalVehicleType!.shortDescription}", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ), ], @@ -196,60 +386,143 @@ class MyRentalBookingScreen extends StatelessWidget { ], ), ), - Text("Package info :".tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Package info :".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - order.rentalPackageModel!.name.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + order + .rentalPackageModel! + .name + .toString(), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), const SizedBox(height: 4), Text( - order.rentalPackageModel!.description.toString(), - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + order + .rentalPackageModel! + .description + .toString(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ], ), ), SizedBox(width: 10), Text( - Constant.amountShow(amount: order.rentalPackageModel!.baseFare.toString()), - style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + order + .rentalPackageModel! + .baseFare + .toString(), + ), + style: + AppThemeData.boldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), - if (Constant.isEnableOTPTripStartForRental == true) - Text("${'OTP :'.tr()} ${order.otpCode}", style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + if (Constant + .isEnableOTPTripStartForRental == + true) + Text( + "${'OTP :'.tr()} ${order.otpCode}", + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), SizedBox(height: 10), Row( children: [ - order.status == Constant.orderInTransit && order.paymentStatus == false + order.status == + Constant + .orderInTransit && + order.paymentStatus == false ? Expanded( child: RoundedButtonFill( title: "Pay Now", onPress: () { - Get.to(() => RentalOrderDetailsScreen(), arguments: order); + Get.to( + () => + RentalOrderDetailsScreen(), + arguments: order, + ); }, - color: AppThemeData.primary300, - textColor: AppThemeData.grey900, + color: + AppThemeData.primary300, + textColor: + AppThemeData.grey900, ), ) : SizedBox(), - order.status == Constant.orderPlaced || order.status == Constant.driverAccepted + order.status == + Constant.orderPlaced || + order.status == + Constant.driverAccepted ? Expanded( child: RoundedButtonFill( title: "Cancel Booking", - onPress: () => controller.cancelRentalRequest(order, taxList: order.taxSetting), - color: AppThemeData.danger300, - textColor: AppThemeData.surface, + onPress: + () => controller + .cancelRentalRequest( + order, + taxList: + order + .taxSetting, + ), + color: + AppThemeData.danger300, + textColor: + AppThemeData.surface, ), ) : SizedBox(), @@ -269,7 +542,12 @@ class MyRentalBookingScreen extends StatelessWidget { ); } - Obx cardDecoration(MyRentalBookingController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + MyRentalBookingController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -284,8 +562,21 @@ class MyRentalBookingScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -296,12 +587,30 @@ class MyRentalBookingScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: Constant.userModel!.walletAmount == null ? '0.0' : Constant.userModel!.walletAmount.toString()), + Constant.amountShow( + amount: + Constant.userModel!.walletAmount == null + ? '0.0' + : Constant.userModel!.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -310,14 +619,23 @@ class MyRentalBookingScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/rental_service/rental_conformation_screen.dart b/lib/screen_ui/rental_service/rental_conformation_screen.dart index 1c2419c..92ac2a1 100644 --- a/lib/screen_ui/rental_service/rental_conformation_screen.dart +++ b/lib/screen_ui/rental_service/rental_conformation_screen.dart @@ -7,7 +7,7 @@ import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/rental_conformation_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../themes/app_them_data.dart'; @@ -38,12 +38,30 @@ class RentalConformationScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Confirm Rent a Car".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Confirm Rent a Car".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -61,26 +79,56 @@ class RentalConformationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset("assets/icons/pickup.png", height: 15, width: 15), + Image.asset( + "assets/icons/pickup.png", + height: 15, + width: 15, + ), SizedBox(width: 15), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${controller.rentalOrderModel.value.sourceLocationName}", - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), Text( - Constant.timestampToDate(controller.rentalOrderModel.value.bookingDateTime!), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + Constant.timestampToDate( + controller + .rentalOrderModel + .value + .bookingDateTime!, + ), + style: AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), ], ), @@ -92,38 +140,96 @@ class RentalConformationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Your Preference".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Your Preference".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), SizedBox(height: 10), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.rentalOrderModel.value.rentalPackageModel!.name.toString(), - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller + .rentalOrderModel + .value + .rentalPackageModel! + .name + .toString(), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), const SizedBox(height: 4), Text( - controller.rentalOrderModel.value.rentalPackageModel!.description.toString(), - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + controller + .rentalOrderModel + .value + .rentalPackageModel! + .description + .toString(), + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), ], ), ), SizedBox(width: 10), Text( - Constant.amountShow(amount: controller.rentalOrderModel.value.rentalPackageModel!.baseFare.toString()), - style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + controller + .rentalOrderModel + .value + .rentalPackageModel! + .baseFare + .toString(), + ), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -134,35 +240,81 @@ class RentalConformationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Vehicle Type".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Vehicle Type".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), SizedBox(height: 10), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( - borderRadius: BorderRadiusGeometry.circular(10), - child: NetworkImageWidget(imageUrl: controller.rentalOrderModel.value.rentalVehicleType!.rentalVehicleIcon.toString(), height: 50, width: 50, borderRadius: 10), + borderRadius: + BorderRadiusGeometry.circular(10), + child: NetworkImageWidget( + imageUrl: + controller + .rentalOrderModel + .value + .rentalVehicleType! + .rentalVehicleIcon + .toString(), + height: 50, + width: 50, + borderRadius: 10, + ), ), SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${controller.rentalOrderModel.value.rentalVehicleType!.name}", - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), Text( "${controller.rentalOrderModel.value.rentalVehicleType!.shortDescription}", - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark600 + : AppThemeData.grey600, + ), ), ], ), @@ -176,24 +328,53 @@ class RentalConformationScreen extends StatelessWidget { Row( children: [ - Expanded(child: Text("Coupons".tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Expanded( + child: Text( + "Coupons".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + ), InkWell( onTap: () { Get.to(RentalCouponScreen())!.then((value) { if (value != null) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: value); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = value; + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: value, + ); + if (couponAmount < + controller.subTotal.value) { + controller.selectedCouponModel.value = + value; controller.calculateAmount(); } else { - ShowToastDialog.showToast("This offer not eligible for this booking".tr()); + ShowToastDialog.showToast( + "This offer not eligible for this booking" + .tr(), + ); } } }); }, child: Text( "View All".tr(), - style: AppThemeData.boldTextStyle(decoration: TextDecoration.underline, fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.boldTextStyle( + decoration: TextDecoration.underline, + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ), ], @@ -202,21 +383,44 @@ class RentalConformationScreen extends StatelessWidget { // Coupon input DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: isDark ? AppThemeData.parcelServiceDark300 : AppThemeData.primary300), + options: RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular(10), + color: + isDark + ? AppThemeData.parcelServiceDark300 + : AppThemeData.primary300, + ), child: Container( - decoration: BoxDecoration(color: AppThemeData.parcelService50, borderRadius: BorderRadius.circular(10)), - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: AppThemeData.parcelService50, + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), child: Row( children: [ - SvgPicture.asset("assets/icons/ic_coupon_parcel.svg", height: 28, width: 28), + SvgPicture.asset( + "assets/icons/ic_coupon_parcel.svg", + height: 28, + width: 28, + ), SizedBox(width: 15), Expanded( child: TextFormField( - controller: controller.couponController.value, - style: AppThemeData.semiBoldTextStyle(color: AppThemeData.grey900), + controller: + controller.couponController.value, + style: AppThemeData.semiBoldTextStyle( + color: AppThemeData.grey900, + ), decoration: InputDecoration( hintText: "Write coupon code".tr(), - hintStyle: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.parcelService500), + hintStyle: AppThemeData.mediumTextStyle( + fontSize: 16, + color: AppThemeData.parcelService500, + ), border: InputBorder.none, ), ), @@ -224,22 +428,61 @@ class RentalConformationScreen extends StatelessWidget { RoundedButtonFill( title: "Redeem now".tr(), onPress: () { - if (controller.couponList.where((element) => element.code!.toLowerCase() == controller.couponController.value.text.toLowerCase()).isNotEmpty) { - CouponModel couponModel = controller.couponList.firstWhere((p0) => p0.code!.toLowerCase() == controller.couponController.value.text.toLowerCase()); - if (couponModel.expiresAt!.toDate().isAfter(DateTime.now())) { - double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: couponModel); - if (couponAmount < controller.subTotal.value) { - controller.selectedCouponModel.value = couponModel; + if (controller.couponList + .where( + (element) => + element.code!.toLowerCase() == + controller + .couponController + .value + .text + .toLowerCase(), + ) + .isNotEmpty) { + CouponModel couponModel = controller + .couponList + .firstWhere( + (p0) => + p0.code!.toLowerCase() == + controller + .couponController + .value + .text + .toLowerCase(), + ); + if (couponModel.expiresAt! + .toDate() + .isAfter(DateTime.now())) { + double couponAmount = + Constant.calculateDiscount( + amount: + controller.subTotal.value + .toString(), + offerModel: couponModel, + ); + if (couponAmount < + controller.subTotal.value) { + controller + .selectedCouponModel + .value = couponModel; controller.calculateAmount(); controller.update(); } else { - ShowToastDialog.showToast("This offer not eligible for this booking".tr()); + ShowToastDialog.showToast( + "This offer not eligible for this booking" + .tr(), + ); } } else { - ShowToastDialog.showToast("This coupon code has been expired".tr()); + ShowToastDialog.showToast( + "This coupon code has been expired" + .tr(), + ); } } else { - ShowToastDialog.showToast("Invalid coupon code".tr()); + ShowToastDialog.showToast( + "Invalid coupon code".tr(), + ); } }, borderRadius: 10, @@ -257,45 +500,104 @@ class RentalConformationScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Order Summary".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500)), + Text( + "Order Summary".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey500, + ), + ), const SizedBox(height: 8), // Subtotal - _summaryTile("Subtotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark, null), + _summaryTile( + "Subtotal".tr(), + Constant.amountShow( + amount: + controller.subTotal.value.toString(), + ), + isDark, + null, + ), // Discount - _summaryTile("Discount".tr(), Constant.amountShow(amount: controller.discount.value.toString()), isDark, AppThemeData.dangerDark300), + _summaryTile( + "Discount".tr(), + Constant.amountShow( + amount: + controller.discount.value.toString(), + ), + isDark, + AppThemeData.dangerDark300, + ), // Tax List - ...List.generate(controller.rentalOrderModel.value.taxSetting!.length, (index) { - final taxModel = controller.rentalOrderModel.value.taxSetting![index]; - final taxTitle = "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; + ...List.generate( + controller + .rentalOrderModel + .value + .taxSetting! + .length, + (index) { + final taxModel = + controller + .rentalOrderModel + .value + .taxSetting![index]; + final taxTitle = + "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; - return _summaryTile( - taxTitle, - Constant.amountShow( - amount: - Constant.getTaxValue( - amount: (controller.subTotal.value - controller.discount.value).toString(), - taxModel: controller.rentalOrderModel.value.taxSetting![index], - ).toString(), - ), - isDark, - null, - ); - }), + return _summaryTile( + taxTitle, + Constant.amountShow( + amount: + Constant.getTaxValue( + amount: + (controller.subTotal.value - + controller + .discount + .value) + .toString(), + taxModel: + controller + .rentalOrderModel + .value + .taxSetting![index], + ).toString(), + ), + isDark, + null, + ); + }, + ), const Divider(), // Total - _summaryTile("Order Total".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark, null), + _summaryTile( + "Order Total".tr(), + Constant.amountShow( + amount: + controller.totalAmount.value.toString(), + ), + isDark, + null, + ), ], ), ), @@ -324,8 +626,22 @@ class RentalConformationScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: title == "Order Total" ? 18 : 16, color: colors ?? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Text( + title, + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: title == "Order Total" ? 18 : 16, + color: + colors ?? + (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ), + ), ], ), ); diff --git a/lib/screen_ui/rental_service/rental_coupon_screen.dart b/lib/screen_ui/rental_service/rental_coupon_screen.dart index 2ce13d3..c1e2c6b 100644 --- a/lib/screen_ui/rental_service/rental_coupon_screen.dart +++ b/lib/screen_ui/rental_service/rental_coupon_screen.dart @@ -8,7 +8,7 @@ import 'package:customer/widget/my_separator.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; class RentalCouponScreen extends StatelessWidget { const RentalCouponScreen({super.key}); @@ -33,12 +33,30 @@ class RentalCouponScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Coupon".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Coupon".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -54,17 +72,35 @@ class RentalCouponScreen extends StatelessWidget { itemBuilder: (context, index) { CouponModel couponModel = controller.cabCouponList[index]; return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Container( height: Responsive.height(16, context), - decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), + decoration: ShapeDecoration( + color: + isDark + ? AppThemeData.grey900 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: Row( children: [ ClipRRect( - borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), child: Stack( children: [ - Image.asset("assets/images/ic_coupon_image.png", height: Responsive.height(16, context), fit: BoxFit.fill), + Image.asset( + "assets/images/ic_coupon_image.png", + height: Responsive.height(16, context), + fit: BoxFit.fill, + ), Padding( padding: const EdgeInsets.only(left: 10), child: Align( @@ -74,7 +110,14 @@ class RentalCouponScreen extends StatelessWidget { child: Text( "${couponModel.discountType == "Fix Price" ? Constant.amountShow(amount: couponModel.discount) : "${couponModel.discount}%"} ${'Off'.tr()}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey50), + style: TextStyle( + fontFamily: AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey50, + ), ), ), ), @@ -84,24 +127,53 @@ class RentalCouponScreen extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 18, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ DottedBorder( - options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(6), color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + options: + RoundedRectDottedBorderOptions( + strokeWidth: 1, + radius: const Radius.circular( + 6, + ), + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: + const EdgeInsets.symmetric( + horizontal: 16, + ), child: Text( "${couponModel.code}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500), + style: TextStyle( + fontFamily: + AppThemeData.semiBold, + fontSize: 16, + color: + isDark + ? AppThemeData.grey400 + : AppThemeData + .grey500, + ), ), ), ), - const Expanded(child: SizedBox(height: 10)), + const Expanded( + child: SizedBox(height: 10), + ), InkWell( onTap: () { Get.back(result: couponModel); @@ -109,18 +181,38 @@ class RentalCouponScreen extends StatelessWidget { child: Text( "Tap To Apply".tr(), textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: TextStyle( + fontFamily: AppThemeData.medium, + color: + isDark + ? AppThemeData + .primary300 + : AppThemeData + .primary300, + ), ), ), ], ), const SizedBox(height: 20), - MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), + MySeparator( + color: + isDark + ? AppThemeData.grey700 + : AppThemeData.grey200, + ), const SizedBox(height: 20), Text( "${couponModel.description}", textAlign: TextAlign.start, - style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: TextStyle( + fontFamily: AppThemeData.medium, + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ], ), diff --git a/lib/screen_ui/rental_service/rental_dashboard_screen.dart b/lib/screen_ui/rental_service/rental_dashboard_screen.dart index ae0e79f..549f827 100644 --- a/lib/screen_ui/rental_service/rental_dashboard_screen.dart +++ b/lib/screen_ui/rental_service/rental_dashboard_screen.dart @@ -5,7 +5,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/cab_rental_dashboard_controllers.dart'; class RentalDashboardScreen extends StatelessWidget { @@ -26,12 +26,19 @@ class RentalDashboardScreen extends StatelessWidget { showUnselectedLabels: true, showSelectedLabels: true, selectedFontSize: 12, - selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), - unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold), + selectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), + unselectedLabelStyle: const TextStyle( + fontFamily: AppThemeData.bold, + ), currentIndex: controller.selectedIndex.value, - backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50, - selectedItemColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, - unselectedItemColor: isDark ? AppThemeData.grey300 : AppThemeData.grey600, + backgroundColor: + isDark ? AppThemeData.grey900 : AppThemeData.grey50, + selectedItemColor: + isDark ? AppThemeData.primary300 : AppThemeData.primary300, + unselectedItemColor: + isDark ? AppThemeData.grey300 : AppThemeData.grey600, onTap: (int index) { if (index == 0) { Get.put(CabDashboardController()); @@ -41,15 +48,57 @@ class RentalDashboardScreen extends StatelessWidget { items: Constant.walletSetting == false ? [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_cab.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_booking_cab.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ] : [ - navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller), - navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller), - navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_wallet_cab.svg", label: 'Wallet'.tr(), controller: controller), - navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller), + navigationBarItem( + isDark, + index: 0, + assetIcon: "assets/icons/ic_home_cab.svg", + label: 'Home'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 1, + assetIcon: "assets/icons/ic_booking_cab.svg", + label: 'My Bookings'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 2, + assetIcon: "assets/icons/ic_wallet_cab.svg", + label: 'Wallet'.tr(), + controller: controller, + ), + navigationBarItem( + isDark, + index: 3, + assetIcon: "assets/icons/ic_profile.svg", + label: 'Profile'.tr(), + controller: controller, + ), ], ), ); @@ -58,7 +107,13 @@ class RentalDashboardScreen extends StatelessWidget { }); } - BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required CabRentalDashboardControllers controller}) { + BottomNavigationBarItem navigationBarItem( + isDark, { + required int index, + required String label, + required String assetIcon, + required CabRentalDashboardControllers controller, + }) { return BottomNavigationBarItem( icon: Padding( padding: const EdgeInsets.symmetric(vertical: 5), diff --git a/lib/screen_ui/rental_service/rental_home_screen.dart b/lib/screen_ui/rental_service/rental_home_screen.dart index 30f7ca1..0ba3a0d 100644 --- a/lib/screen_ui/rental_service/rental_home_screen.dart +++ b/lib/screen_ui/rental_service/rental_home_screen.dart @@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:customer/constant/constant.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/rental_home_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../models/rental_vehicle_type.dart'; @@ -44,8 +44,20 @@ class RentalHomeScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), @@ -58,9 +70,21 @@ class RentalHomeScreen extends StatelessWidget { onTap: () { Get.offAll(const LoginScreen()); }, - child: Text("Login".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900)), + child: Text( + "Login".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), + ), ) - : Text(Constant.userModel!.fullName(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900)), + : Text( + Constant.userModel!.fullName(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -82,30 +106,69 @@ class RentalHomeScreen extends StatelessWidget { InkWell( onTap: () async { if (Constant.selectedMapType == 'osm') { - final result = await Get.to(() => MapPickerPage()); + final result = await Get.to( + () => MapPickerPage(), + ); if (result != null) { final firstPlace = result; - if (Constant.checkZoneCheck(firstPlace.coordinates.latitude, firstPlace.coordinates.longitude) == true) { + if (Constant.checkZoneCheck( + firstPlace.coordinates.latitude, + firstPlace.coordinates.longitude, + ) == + true) { final address = firstPlace.address; final lat = firstPlace.coordinates.latitude; - final lng = firstPlace.coordinates.longitude; - controller.sourceTextEditController.value.text = address; - controller.departureLatLongOsm.value = latlong.LatLng(lat, lng); + final lng = + firstPlace.coordinates.longitude; + controller + .sourceTextEditController + .value + .text = address; + controller + .departureLatLongOsm + .value = latlong.LatLng(lat, lng); } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } } } else { - Get.to(LocationPickerScreen())!.then((value) async { + Get.to(LocationPickerScreen())!.then(( + value, + ) async { if (value != null) { - SelectedLocationModel selectedLocationModel = value; + SelectedLocationModel + selectedLocationModel = value; - if (Constant.checkZoneCheck(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude) == true) { - controller.sourceTextEditController.value.text = Utils.formatAddress(selectedLocation: selectedLocationModel); - controller.departureLatLong.value = latlong.LatLng(selectedLocationModel.latLng!.latitude, selectedLocationModel.latLng!.longitude); + if (Constant.checkZoneCheck( + selectedLocationModel + .latLng! + .latitude, + selectedLocationModel + .latLng! + .longitude, + ) == + true) { + controller + .sourceTextEditController + .value + .text = Utils.formatAddress( + selectedLocation: selectedLocationModel, + ); + controller + .departureLatLong + .value = latlong.LatLng( + selectedLocationModel.latLng!.latitude, + selectedLocationModel.latLng!.longitude, + ); } else { - ShowToastDialog.showToast("Service is unavailable at the selected address.".tr()); + ShowToastDialog.showToast( + "Service is unavailable at the selected address." + .tr(), + ); } } }); @@ -113,11 +176,18 @@ class RentalHomeScreen extends StatelessWidget { }, hoverColor: Colors.transparent, child: TextFieldWidget( - controller: controller.sourceTextEditController.value, + controller: + controller.sourceTextEditController.value, hintText: "Your current location".tr(), title: "Pickup Location".tr(), enable: false, - prefix: Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Icon(Icons.stop_circle_outlined, color: Colors.green)), + prefix: Padding( + padding: EdgeInsets.only(left: 10, right: 10), + child: Icon( + Icons.stop_circle_outlined, + color: Colors.green, + ), + ), ), ), const SizedBox(height: 25), @@ -125,7 +195,16 @@ class RentalHomeScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Select Your Vehicle Type".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Select Your Vehicle Type".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), const SizedBox(width: 10), GestureDetector( onTap: () => controller.pickDate(context), @@ -133,7 +212,13 @@ class RentalHomeScreen extends StatelessWidget { children: [ Text( "${controller.selectedDate.value.day}-${controller.selectedDate.value.month}-${controller.selectedDate.value.year}", - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), ), const SizedBox(width: 5), const Icon(Icons.date_range, size: 20), @@ -150,11 +235,13 @@ class RentalHomeScreen extends StatelessWidget { physics: NeverScrollableScrollPhysics(), scrollDirection: Axis.vertical, itemBuilder: (context, index) { - RentalVehicleType vehicleType = controller.vehicleTypes[index]; + RentalVehicleType vehicleType = + controller.vehicleTypes[index]; return Obx( () => InkWell( onTap: () { - controller.selectedVehicleType.value = controller.vehicleTypes[index]; + controller.selectedVehicleType.value = + controller.vehicleTypes[index]; }, child: Padding( padding: const EdgeInsets.only(bottom: 10), @@ -164,72 +251,144 @@ class RentalHomeScreen extends StatelessWidget { border: Border.all( color: isDark - ? controller.selectedVehicleType.value?.id == vehicleType.id - ? AppThemeData.carRentDark300 + ? controller + .selectedVehicleType + .value + ?.id == + vehicleType.id + ? AppThemeData + .carRentDark300 : Colors.transparent - : controller.selectedVehicleType.value?.id == vehicleType.id + : controller + .selectedVehicleType + .value + ?.id == + vehicleType.id ? AppThemeData.carRent300 : Colors.transparent, width: 1, ), color: - controller.selectedVehicleType.value?.id == vehicleType.id + controller + .selectedVehicleType + .value + ?.id == + vehicleType.id ? AppThemeData.carRent50 : isDark ? AppThemeData.carRentDark50 : Colors.white, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), child: Row( children: [ ClipRRect( //borderRadius: BorderRadius.circular(10), child: CachedNetworkImage( - imageUrl: vehicleType.rentalVehicleIcon.toString(), + imageUrl: + vehicleType + .rentalVehicleIcon + .toString(), height: 60, width: 60, imageBuilder: - (context, imageProvider) => - Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))), - placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))), - errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover), + ( + context, + imageProvider, + ) => Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 10, + ), + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: + (context, url) => Center( + child: CircularProgressIndicator.adaptive( + valueColor: + AlwaysStoppedAnimation( + AppThemeData + .primary300, + ), + ), + ), + errorWidget: + (context, url, error) => + Image.network( + Constant + .placeHolderImage, + fit: BoxFit.cover, + ), fit: BoxFit.cover, ), ), Expanded( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: + const EdgeInsets.symmetric( + horizontal: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "${vehicleType.name}", style: TextStyle( fontSize: 16, - fontWeight: FontWeight.bold, + fontWeight: + FontWeight.bold, letterSpacing: 1, color: isDark - ? controller.selectedVehicleType.value?.id == vehicleType.id - ? AppThemeData.greyDark50 - : AppThemeData.grey50 - : AppThemeData.greyDark50, + ? controller + .selectedVehicleType + .value + ?.id == + vehicleType + .id + ? AppThemeData + .greyDark50 + : AppThemeData + .grey50 + : AppThemeData + .greyDark50, ), ), Padding( - padding: const EdgeInsets.only(top: 2.0), + padding: + const EdgeInsets.only( + top: 2.0, + ), child: Text( "${vehicleType.description}", style: TextStyle( - fontWeight: FontWeight.w400, + fontWeight: + FontWeight.w400, letterSpacing: 1, color: isDark - ? controller.selectedVehicleType.value?.id == vehicleType.id - ? AppThemeData.greyDark50 - : AppThemeData.grey50 - : AppThemeData.greyDark50, + ? controller + .selectedVehicleType + .value + ?.id == + vehicleType + .id + ? AppThemeData + .greyDark50 + : AppThemeData + .grey50 + : AppThemeData + .greyDark50, ), ), ), @@ -250,30 +409,46 @@ class RentalHomeScreen extends StatelessWidget { RoundedButtonFill( title: "Continue".tr(), onPress: () async { - final sourceText = controller.sourceTextEditController.value.text.trim(); + final sourceText = + controller.sourceTextEditController.value.text + .trim(); if (Constant.userModel == null) { - ShowToastDialog.showToast("Please login to continue".tr()); + ShowToastDialog.showToast( + "Please login to continue".tr(), + ); return; } if (sourceText.isEmpty) { - ShowToastDialog.showToast("Please select source location".tr()); + ShowToastDialog.showToast( + "Please select source location".tr(), + ); return; } - if (controller.selectedVehicleType.value == null) { - ShowToastDialog.showToast("Please select a vehicle type".tr()); + if (controller.selectedVehicleType.value == + null) { + ShowToastDialog.showToast( + "Please select a vehicle type".tr(), + ); return; } await controller.getRentalPackage(); if (controller.rentalPackages.isEmpty) { - ShowToastDialog.showToast("No preference available for the selected vehicle type".tr()); + ShowToastDialog.showToast( + "No preference available for the selected vehicle type" + .tr(), + ); return; } // Open bottom sheet if packages exist - Get.bottomSheet(selectPreferences(context, controller, isDark), isScrollControlled: true, backgroundColor: Colors.transparent); + Get.bottomSheet( + selectPreferences(context, controller, isDark), + isScrollControlled: true, + backgroundColor: Colors.transparent, + ); }, color: AppThemeData.primary300, textColor: AppThemeData.grey900, @@ -289,7 +464,11 @@ class RentalHomeScreen extends StatelessWidget { ); } - Widget selectPreferences(BuildContext context, RentalHomeController controller, bool isDark) { + Widget selectPreferences( + BuildContext context, + RentalHomeController controller, + bool isDark, + ) { return DraggableScrollableSheet( initialChildSize: 0.40, minChildSize: 0.40, @@ -297,19 +476,39 @@ class RentalHomeScreen extends StatelessWidget { expand: false, builder: (context, scrollController) { return Container( - decoration: BoxDecoration(color: isDark ? Colors.black : Colors.white, borderRadius: const BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? Colors.black : Colors.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), child: Column( children: [ // handle bar - Container(height: 4, width: 33, decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.grey.shade400)), + Container( + height: 4, + width: 33, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.grey.shade400, + ), + ), Align( alignment: Alignment.topLeft, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), - child: Text("Select Preferences".tr(), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: isDark ? Colors.white : Colors.black)), + child: Text( + "Select Preferences".tr(), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + color: isDark ? Colors.white : Colors.black, + ), + ), ), ), @@ -321,30 +520,43 @@ class RentalHomeScreen extends StatelessWidget { final package = controller.rentalPackages[index]; return Obx( () => InkWell( - onTap: () => controller.selectedPackage.value = package, + onTap: + () => controller.selectedPackage.value = package, child: Container( margin: const EdgeInsets.symmetric(vertical: 6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all( - color: controller.selectedPackage.value?.id == package.id ? (isDark ? AppThemeData.carRentDark300 : AppThemeData.carRent300) : Colors.transparent, + color: + controller.selectedPackage.value?.id == + package.id + ? (isDark + ? AppThemeData.carRentDark300 + : AppThemeData.carRent300) + : Colors.transparent, width: 1, ), color: - controller.selectedPackage.value?.id == package.id + controller.selectedPackage.value?.id == + package.id ? AppThemeData.carRent50 : isDark ? AppThemeData.carRentDark50 : Colors.white, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 12), + padding: const EdgeInsets.symmetric( + vertical: 15, + horizontal: 12, + ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( package.name ?? "", @@ -352,8 +564,13 @@ class RentalHomeScreen extends StatelessWidget { fontSize: 18, color: isDark - ? controller.selectedPackage.value?.id == package.id - ? AppThemeData.greyDark50 + ? controller + .selectedPackage + .value + ?.id == + package.id + ? AppThemeData + .greyDark50 : AppThemeData.grey50 : AppThemeData.greyDark50, ), @@ -365,8 +582,13 @@ class RentalHomeScreen extends StatelessWidget { fontSize: 14, color: isDark - ? controller.selectedPackage.value?.id == package.id - ? AppThemeData.greyDark50 + ? controller + .selectedPackage + .value + ?.id == + package.id + ? AppThemeData + .greyDark50 : AppThemeData.grey50 : AppThemeData.greyDark50, ), @@ -375,12 +597,18 @@ class RentalHomeScreen extends StatelessWidget { ), ), Text( - Constant.amountShow(amount: package.baseFare.toString()), + Constant.amountShow( + amount: package.baseFare.toString(), + ), style: AppThemeData.boldTextStyle( fontSize: 18, color: isDark - ? controller.selectedPackage.value?.id == package.id + ? controller + .selectedPackage + .value + ?.id == + package.id ? AppThemeData.greyDark50 : AppThemeData.grey50 : AppThemeData.greyDark50, @@ -401,7 +629,11 @@ class RentalHomeScreen extends StatelessWidget { RoundedButtonFill( title: "Continue".tr(), onPress: () { - Get.bottomSheet(paymentBottomSheet(context, controller, isDark), isScrollControlled: true, backgroundColor: Colors.transparent); + Get.bottomSheet( + paymentBottomSheet(context, controller, isDark), + isScrollControlled: true, + backgroundColor: Colors.transparent, + ); }, color: AppThemeData.primary300, textColor: AppThemeData.grey900, @@ -414,7 +646,11 @@ class RentalHomeScreen extends StatelessWidget { ); } - Widget paymentBottomSheet(BuildContext context, RentalHomeController controller, bool isDark) { + Widget paymentBottomSheet( + BuildContext context, + RentalHomeController controller, + bool isDark, + ) { return DraggableScrollableSheet( initialChildSize: 0.70, // Start height @@ -427,7 +663,10 @@ class RentalHomeScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey500 : Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey500 : Colors.white, + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -435,8 +674,20 @@ class RentalHomeScreen extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Select Payment Method".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - GestureDetector(onTap: () => Get.back(), child: const Icon(Icons.close)), + Text( + "Select Payment Method".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + GestureDetector( + onTap: () => Get.back(), + child: const Icon(Icons.close), + ), ], ), const SizedBox(height: 20), @@ -447,39 +698,89 @@ class RentalHomeScreen extends StatelessWidget { padding: EdgeInsets.zero, controller: scrollController, children: [ - Text("Preferred Payment".tr(), style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Preferred Payment".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), - Text("Other Payment Options".tr(), style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Other Payment Options".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), ], ), @@ -488,32 +789,129 @@ class RentalHomeScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -530,17 +928,28 @@ class RentalHomeScreen extends StatelessWidget { textColor: AppThemeData.grey900, onPress: () async { if (controller.selectedPaymentMethod.value.isEmpty) { - ShowToastDialog.showToast("Please select a payment method".tr()); + ShowToastDialog.showToast( + "Please select a payment method".tr(), + ); return; } // Only check wallet if payment method is wallet if (controller.selectedPaymentMethod.value == "wallet") { - num walletAmount = controller.userModel.value.walletAmount ?? 0; - num baseFare = double.tryParse(controller.selectedPackage.value?.baseFare.toString() ?? "0") ?? 0; + num walletAmount = + controller.userModel.value.walletAmount ?? 0; + num baseFare = + double.tryParse( + controller.selectedPackage.value?.baseFare + .toString() ?? + "0", + ) ?? + 0; if (walletAmount < baseFare) { - ShowToastDialog.showToast("You do not have sufficient wallet balance".tr()); + ShowToastDialog.showToast( + "You do not have sufficient wallet balance".tr(), + ); return; } } @@ -555,7 +964,12 @@ class RentalHomeScreen extends StatelessWidget { ); } - Obx cardDecoration(RentalHomeController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + RentalHomeController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -570,8 +984,21 @@ class RentalHomeScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -582,12 +1009,34 @@ class RentalHomeScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: controller.userModel.value.walletAmount == null ? '0.0' : controller.userModel.value.walletAmount.toString()), + Constant.amountShow( + amount: + controller.userModel.value.walletAmount == + null + ? '0.0' + : controller + .userModel + .value + .walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -596,14 +1045,23 @@ class RentalHomeScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/rental_service/rental_order_details_screen.dart b/lib/screen_ui/rental_service/rental_order_details_screen.dart index 9b6129a..a6c0821 100644 --- a/lib/screen_ui/rental_service/rental_order_details_screen.dart +++ b/lib/screen_ui/rental_service/rental_order_details_screen.dart @@ -11,7 +11,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/rental_order_details_controller.dart'; import '../../controllers/theme_controller.dart'; import '../../models/user_model.dart'; @@ -46,12 +46,30 @@ class RentalOrderDetailsScreen extends StatelessWidget { child: Container( height: 42, width: 42, - decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50), - child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppThemeData.grey50, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_back_ios, + color: AppThemeData.grey900, + size: 20, + ), + ), + ), ), ), const SizedBox(width: 10), - Text("Order Details".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)), + Text( + "Order Details".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: AppThemeData.grey900, + ), + ), ], ), ), @@ -64,7 +82,10 @@ class RentalOrderDetailsScreen extends StatelessWidget { Expanded( child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 20, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -72,8 +93,16 @@ class RentalOrderDetailsScreen extends StatelessWidget { padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( children: [ @@ -81,15 +110,32 @@ class RentalOrderDetailsScreen extends StatelessWidget { children: [ Expanded( child: Text( - "${'Booking Id :'.tr()} ${controller.order.value.id}", - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark700 + : AppThemeData + .grey700, + ), ), ), InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: controller.order.value.id.toString())); - ShowToastDialog.showToast("Booking ID copied to clipboard".tr()); + Clipboard.setData( + ClipboardData( + text: + controller.order.value.id + .toString(), + ), + ); + ShowToastDialog.showToast( + "Booking ID copied to clipboard" + .tr(), + ); }, child: Icon(Icons.copy), ), @@ -97,22 +143,64 @@ class RentalOrderDetailsScreen extends StatelessWidget { ), SizedBox(height: 10), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Padding(padding: const EdgeInsets.only(top: 5), child: Image.asset("assets/icons/pickup.png", height: 15, width: 15)), + Padding( + padding: const EdgeInsets.only( + top: 5, + ), + child: Image.asset( + "assets/icons/pickup.png", + height: 15, + width: 15, + ), + ), const SizedBox(width: 15), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.order.value.sourceLocationName ?? "-", - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller + .order + .value + .sourceLocationName ?? + "-", + style: + AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), - if (controller.order.value.bookingDateTime != null) + if (controller + .order + .value + .bookingDateTime != + null) Text( - Constant.timestampToDate(controller.order.value.bookingDateTime!), - style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + Constant.timestampToDate( + controller + .order + .value + .bookingDateTime!, + ), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 12, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ], ), @@ -123,43 +211,107 @@ class RentalOrderDetailsScreen extends StatelessWidget { ), ), const SizedBox(height: 15), - if (controller.order.value.rentalPackageModel != null) + if (controller.order.value.rentalPackageModel != + null) Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text("Your Preference".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Your Preference".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), SizedBox(height: 10), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.order.value.rentalPackageModel!.name ?? "-", - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller + .order + .value + .rentalPackageModel! + .name ?? + "-", + style: + AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), const SizedBox(height: 4), Text( - controller.order.value.rentalPackageModel!.description ?? "", - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + controller + .order + .value + .rentalPackageModel! + .description ?? + "", + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ], ), ), const SizedBox(width: 10), Text( - Constant.amountShow(amount: controller.order.value.rentalPackageModel!.baseFare.toString()), - style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + Constant.amountShow( + amount: + controller + .order + .value + .rentalPackageModel! + .baseFare + .toString(), + ), + style: AppThemeData.boldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData.grey900, + ), ), ], ), @@ -172,19 +324,43 @@ class RentalOrderDetailsScreen extends StatelessWidget { children: [ Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + borderRadius: BorderRadius.circular( + 15, + ), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), padding: const EdgeInsets.all(16), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text("About Driver".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "About Driver".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 8), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ @@ -192,109 +368,277 @@ class RentalOrderDetailsScreen extends StatelessWidget { width: 52, height: 52, child: ClipRRect( - borderRadius: BorderRadiusGeometry.circular(10), - child: NetworkImageWidget(imageUrl: controller.driverUser.value?.profilePictureURL ?? '', height: 70, width: 70, borderRadius: 35), + borderRadius: + BorderRadiusGeometry.circular( + 10, + ), + child: NetworkImageWidget( + imageUrl: + controller + .driverUser + .value + ?.profilePictureURL ?? + '', + height: 70, + width: 70, + borderRadius: 35, + ), ), ), SizedBox(width: 20), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, children: [ Text( - controller.order.value.driver?.fullName() ?? '', - style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18), + controller + .order + .value + .driver + ?.fullName() ?? + '', + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + fontSize: 18, + ), ), Text( "${controller.order.value.driver?.vehicleType ?? ''} | ${controller.order.value.driver?.carMakes.toString()}", - style: TextStyle(fontFamily: AppThemeData.medium, color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 14), + style: TextStyle( + fontFamily: + AppThemeData + .medium, + color: + isDark + ? AppThemeData + .greyDark700 + : AppThemeData + .grey700, + fontSize: 14, + ), ), Text( - controller.order.value.driver?.carNumber ?? '', - style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 16), + controller + .order + .value + .driver + ?.carNumber ?? + '', + style: AppThemeData.boldTextStyle( + color: + isDark + ? AppThemeData + .greyDark700 + : AppThemeData + .grey700, + fontSize: 16, + ), ), ], ), ], ), RoundedButtonBorder( - title: controller.driverUser.value?.averageRating.toString() ?? '', + title: + controller + .driverUser + .value + ?.averageRating + .toString() ?? + '', width: 20, height: 3.5, radius: 10, isRight: false, isCenter: true, - textColor: AppThemeData.warning400, - borderColor: AppThemeData.warning400, + textColor: + AppThemeData.warning400, + borderColor: + AppThemeData.warning400, color: AppThemeData.warning50, - icon: SvgPicture.asset("assets/icons/ic_start.svg"), + icon: SvgPicture.asset( + "assets/icons/ic_start.svg", + ), onPress: () {}, ), ], ), Visibility( - visible: controller.order.value.status == Constant.orderCompleted ? true : false, + visible: + controller + .order + .value + .status == + Constant + .orderCompleted + ? true + : false, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: RoundedButtonFill( - title: controller.ratingModel.value.id != null && controller.ratingModel.value.id!.isNotEmpty ? 'Update Review'.tr() : 'Add Review'.tr(), + title: + controller + .ratingModel + .value + .id != + null && + controller + .ratingModel + .value + .id! + .isNotEmpty + ? 'Update Review'.tr() + : 'Add Review'.tr(), onPress: () async { - final result = await Get.to(() => RentalReviewScreen(), arguments: {'order': controller.order.value}); + final result = await Get.to( + () => + RentalReviewScreen(), + arguments: { + 'order': + controller + .order + .value, + }, + ); // If review was submitted successfully if (result == true) { - await controller.fetchDriverDetails(); + await controller + .fetchDriverDetails(); } }, height: 5, borderRadius: 15, color: Colors.orange, - textColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + textColor: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, ), ), ), - controller.order.value.status == Constant.orderCompleted || controller.order.value.status == Constant.orderCancelled + controller.order.value.status == + Constant + .orderCompleted || + controller + .order + .value + .status == + Constant.orderCancelled ? SizedBox() : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, children: [ InkWell( onTap: () { - Constant.makePhoneCall(controller.order.value.driver!.phoneNumber ?? ''); + Constant.makePhoneCall( + controller + .order + .value + .driver! + .phoneNumber ?? + '', + ); }, child: Container( width: 150, height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_phone_call.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_phone_call.svg")), ), ), const SizedBox(width: 10), InkWell( onTap: () async { - ShowToastDialog.showLoader("Please wait...".tr()); + ShowToastDialog.showLoader( + "Please wait...".tr(), + ); - UserModel? customer = await FireStoreUtils.getUserProfile(controller.order.value.authorID ?? ''); - UserModel? driverUser = await FireStoreUtils.getUserProfile(controller.order.value.driverId ?? ''); + UserModel? customer = + await FireStoreUtils.getUserProfile( + controller + .order + .value + .authorID ?? + '', + ); + UserModel? driverUser = + await FireStoreUtils.getUserProfile( + controller + .order + .value + .driverId ?? + '', + ); ShowToastDialog.closeLoader(); Get.to( const ChatScreen(), arguments: { - "customerName": customer?.fullName(), - "restaurantName": driverUser?.fullName(), - "orderId": controller.order.value.id, - "restaurantId": driverUser?.id, - "customerId": customer?.id, - "customerProfileImage": customer?.profilePictureURL, - "restaurantProfileImage": driverUser?.profilePictureURL, - "token": driverUser?.fcmToken, - "chatType": "Driver", + "customerName": + customer + ?.fullName(), + "restaurantName": + driverUser + ?.fullName(), + "orderId": + controller + .order + .value + .id, + "restaurantId": + driverUser?.id, + "customerId": + customer?.id, + "customerProfileImage": + customer + ?.profilePictureURL, + "restaurantProfileImage": + driverUser + ?.profilePictureURL, + "token": + driverUser + ?.fcmToken, + "chatType": + "Driver", }, ); }, @@ -303,11 +647,30 @@ class RentalOrderDetailsScreen extends StatelessWidget { height: 42, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200), - borderRadius: BorderRadius.circular(120), + side: BorderSide( + width: 1, + color: + isDark + ? AppThemeData + .grey700 + : AppThemeData + .grey200, + ), + borderRadius: + BorderRadius.circular( + 120, + ), + ), + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: SvgPicture.asset( + "assets/icons/ic_wechat.svg", ), ), - child: Padding(padding: const EdgeInsets.all(8.0), child: SvgPicture.asset("assets/icons/ic_wechat.svg")), ), ), ], @@ -318,37 +681,96 @@ class RentalOrderDetailsScreen extends StatelessWidget { const SizedBox(height: 15), ], ), - if (controller.order.value.rentalVehicleType != null) + if (controller.order.value.rentalVehicleType != + null) Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text("Vehicle Type".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Vehicle Type".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), SizedBox(height: 10), Row( children: [ ClipRRect( - borderRadius: BorderRadius.circular(10), - child: NetworkImageWidget(imageUrl: controller.order.value.rentalVehicleType!.rentalVehicleIcon ?? "", height: 50, width: 50), + borderRadius: + BorderRadius.circular(10), + child: NetworkImageWidget( + imageUrl: + controller + .order + .value + .rentalVehicleType! + .rentalVehicleIcon ?? + "", + height: 50, + width: 50, + ), ), const SizedBox(width: 10), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - controller.order.value.rentalVehicleType!.name ?? "", - style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + controller + .order + .value + .rentalVehicleType! + .name ?? + "", + style: + AppThemeData.semiBoldTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), Text( - controller.order.value.rentalVehicleType!.shortDescription ?? "", - style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600), + controller + .order + .value + .rentalVehicleType! + .shortDescription ?? + "", + style: + AppThemeData.mediumTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData + .greyDark600 + : AppThemeData + .grey600, + ), ), ], ), @@ -365,107 +787,249 @@ class RentalOrderDetailsScreen extends StatelessWidget { width: Responsive.width(100, context), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text("Rental Details".tr(), style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), - Divider(color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300), + Text( + "Rental Details".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), + Divider( + color: + isDark + ? AppThemeData.greyDark300 + : AppThemeData.grey300, + ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( 'Rental Package'.tr(), textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( - controller.order.value.rentalPackageModel!.name.toString().tr(), + controller + .order + .value + .rentalPackageModel! + .name + .toString() + .tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( 'Rental Package Price'.tr(), textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( - Constant.amountShow(amount: controller.order.value.rentalPackageModel!.baseFare.toString()).tr(), + Constant.amountShow( + amount: + controller + .order + .value + .rentalPackageModel! + .baseFare + .toString(), + ).tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( '${'Including'.tr()} ${Constant.distanceType.tr()}', textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( - "${controller.order.value.rentalPackageModel!.includedDistance.toString()} ${Constant.distanceType}".tr(), + "${controller.order.value.rentalPackageModel!.includedDistance.toString()} ${Constant.distanceType}" + .tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( 'Including Hours'.tr(), textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( - "${controller.order.value.rentalPackageModel!.includedHours.toString()} ${'Hr'.tr()}".tr(), + "${controller.order.value.rentalPackageModel!.includedHours.toString()} ${'Hr'.tr()}" + .tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( '${'Extra'.tr()} ${Constant.distanceType}', textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( controller.getExtraKm(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), @@ -493,20 +1057,41 @@ class RentalOrderDetailsScreen extends StatelessWidget { controller.order.value.endTime == null ? SizedBox() : Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: + const EdgeInsets.symmetric( + vertical: 10, + ), child: Row( children: [ Expanded( child: Text( 'Extra Minutes'.tr(), - textAlign: TextAlign.start, - style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + textAlign: + TextAlign.start, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ), Text( "${controller.order.value.endTime == null ? "0" : (((controller.order.value.endTime!.toDate().difference(controller.order.value.startTime!.toDate()).inMinutes) - (int.parse(controller.order.value.rentalPackageModel!.includedHours.toString()) * 60)).clamp(0, double.infinity).toInt().toString())} ${'Min'.tr()}", textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + style: + AppThemeData.boldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData + .greyDark900 + : AppThemeData + .grey900, + ), ), ], ), @@ -520,31 +1105,99 @@ class RentalOrderDetailsScreen extends StatelessWidget { padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text("Order Summary".tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500)), + Text( + "Order Summary".tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: AppThemeData.grey500, + ), + ), const SizedBox(height: 8), - _summaryTile("Subtotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark, null), - _summaryTile("Discount".tr(), Constant.amountShow(amount: controller.discount.value.toString()), isDark, AppThemeData.dangerDark300), + _summaryTile( + "Subtotal".tr(), + Constant.amountShow( + amount: + controller.subTotal.value + .toString(), + ), + isDark, + null, + ), + _summaryTile( + "Discount".tr(), + Constant.amountShow( + amount: + controller.discount.value + .toString(), + ), + isDark, + AppThemeData.dangerDark300, + ), - ...List.generate(controller.order.value.taxSetting?.length ?? 0, (index) { - final taxModel = controller.order.value.taxSetting![index]; - final taxTitle = "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; - return _summaryTile( - taxTitle, - Constant.amountShow(amount: Constant.getTaxValue(amount: (controller.subTotal.value - controller.discount.value).toString(), taxModel: taxModel).toString()), - isDark, - null, - ); - }), + ...List.generate( + controller + .order + .value + .taxSetting + ?.length ?? + 0, + (index) { + final taxModel = + controller + .order + .value + .taxSetting![index]; + final taxTitle = + "${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}"; + return _summaryTile( + taxTitle, + Constant.amountShow( + amount: + Constant.getTaxValue( + amount: + (controller + .subTotal + .value - + controller + .discount + .value) + .toString(), + taxModel: taxModel, + ).toString(), + ), + isDark, + null, + ); + }, + ), const Divider(), - _summaryTile("Order Total".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark, null), + _summaryTile( + "Order Total".tr(), + Constant.amountShow( + amount: + controller.totalAmount.value + .toString(), + ), + isDark, + null, + ), ], ), ), @@ -554,32 +1207,66 @@ class RentalOrderDetailsScreen extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), child: Row( children: [ - if (controller.order.value.status == Constant.orderInTransit && controller.order.value.paymentStatus == false) + if (controller.order.value.status == + Constant.orderInTransit && + controller.order.value.paymentStatus == false) Expanded( child: RoundedButtonFill( title: "Pay Now", onPress: () { - if (controller.order.value.endKitoMetersReading == null || - controller.order.value.endKitoMetersReading == "0.0" || - controller.order.value.endKitoMetersReading!.isEmpty) { - ShowToastDialog.showToast("You are not able to pay now until driver adds kilometer".tr()); + if (controller + .order + .value + .endKitoMetersReading == + null || + controller + .order + .value + .endKitoMetersReading == + "0.0" || + controller + .order + .value + .endKitoMetersReading! + .isEmpty) { + ShowToastDialog.showToast( + "You are not able to pay now until driver adds kilometer" + .tr(), + ); } else { - Get.bottomSheet(paymentBottomSheet(context, controller, isDark, controller.order.value), isScrollControlled: true, backgroundColor: Colors.transparent); + Get.bottomSheet( + paymentBottomSheet( + context, + controller, + isDark, + controller.order.value, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent, + ); } }, color: AppThemeData.primary300, textColor: AppThemeData.grey900, ), ), - if (controller.order.value.status == Constant.orderPlaced || controller.order.value.status == Constant.driverAccepted) + if (controller.order.value.status == + Constant.orderPlaced || + controller.order.value.status == + Constant.driverAccepted) Expanded( child: RoundedButtonFill( title: "Cancel Booking", onPress: () { - controller.cancelRentalRequest(controller.order.value); + controller.cancelRentalRequest( + controller.order.value, + ); }, color: AppThemeData.danger300, textColor: AppThemeData.surface, @@ -601,14 +1288,33 @@ class RentalOrderDetailsScreen extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), - Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: title == "Order Total" ? 18 : 16, color: colors ?? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))), + Text( + title, + style: AppThemeData.mediumTextStyle( + fontSize: 16, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), + Text( + value, + style: AppThemeData.semiBoldTextStyle( + fontSize: title == "Order Total" ? 18 : 16, + color: + colors ?? + (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), + ), + ), ], ), ); } - Widget paymentBottomSheet(BuildContext context, RentalOrderDetailsController controller, bool isDark, RentalOrderModel orderModel) { + Widget paymentBottomSheet( + BuildContext context, + RentalOrderDetailsController controller, + bool isDark, + RentalOrderModel orderModel, + ) { return DraggableScrollableSheet( initialChildSize: 0.70, // Start height @@ -621,14 +1327,26 @@ class RentalOrderDetailsScreen extends StatelessWidget { builder: (context, scrollController) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - decoration: BoxDecoration(color: isDark ? AppThemeData.grey500 : Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + decoration: BoxDecoration( + color: isDark ? AppThemeData.grey500 : Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Select Payment Method".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + "Select Payment Method".tr(), + style: AppThemeData.mediumTextStyle( + fontSize: 18, + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + ), + ), GestureDetector( onTap: () { Get.back(); @@ -643,32 +1361,74 @@ class RentalOrderDetailsScreen extends StatelessWidget { padding: EdgeInsets.zero, controller: scrollController, children: [ - Text("Preferred Payment".tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)), + Text( + "Preferred Payment".tr(), + textAlign: TextAlign.start, + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), + ), const SizedBox(height: 10), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Visibility( - visible: controller.walletSettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"), + visible: + controller + .walletSettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.wallet, + isDark, + "assets/images/ic_wallet.png", + ), ), Visibility( - visible: controller.cashOnDeliverySettingModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"), + visible: + controller + .cashOnDeliverySettingModel + .value + .isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.cod, + isDark, + "assets/images/ic_cash.png", + ), ), ], ), ), ), - if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true) + if (controller.walletSettingModel.value.isEnabled == true || + controller.cashOnDeliverySettingModel.value.isEnabled == + true) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -676,7 +1436,13 @@ class RentalOrderDetailsScreen extends StatelessWidget { Text( "Other Payment Options".tr(), textAlign: TextAlign.start, - style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500), + style: AppThemeData.boldTextStyle( + fontSize: 15, + color: + isDark + ? AppThemeData.greyDark500 + : AppThemeData.grey500, + ), ), const SizedBox(height: 10), ], @@ -684,32 +1450,129 @@ class RentalOrderDetailsScreen extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + border: Border.all( + color: + isDark + ? AppThemeData.greyDark200 + : AppThemeData.grey200, + ), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")), - Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")), - Visibility(visible: controller.payStackModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png")), Visibility( - visible: controller.mercadoPagoModel.value.isEnabled == true, - child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"), + visible: + controller.stripeModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.stripe, + isDark, + "assets/images/stripe.png", + ), ), Visibility( - visible: controller.flutterWaveModel.value.isEnable == true, - child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"), + visible: + controller.payPalModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.paypal, + isDark, + "assets/images/paypal.png", + ), ), - Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")), - Visibility(visible: controller.razorPayModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png")), - Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")), Visibility( - visible: controller.orangeMoneyModel.value.enable == true, - child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"), + visible: + controller.payStackModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payStack, + isDark, + "assets/images/paystack.png", + ), + ), + Visibility( + visible: + controller.mercadoPagoModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.mercadoPago, + isDark, + "assets/images/mercado-pago.png", + ), + ), + Visibility( + visible: + controller.flutterWaveModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.flutterWave, + isDark, + "assets/images/flutterwave_logo.png", + ), + ), + Visibility( + visible: + controller.payFastModel.value.isEnable == + true, + child: cardDecoration( + controller, + PaymentGateway.payFast, + isDark, + "assets/images/payfast.png", + ), + ), + Visibility( + visible: + controller.razorPayModel.value.isEnabled == + true, + child: cardDecoration( + controller, + PaymentGateway.razorpay, + isDark, + "assets/images/razorpay.png", + ), + ), + Visibility( + visible: + controller.midTransModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.midTrans, + isDark, + "assets/images/midtrans.png", + ), + ), + Visibility( + visible: + controller.orangeMoneyModel.value.enable == + true, + child: cardDecoration( + controller, + PaymentGateway.orangeMoney, + isDark, + "assets/images/orange_money.png", + ), + ), + Visibility( + visible: + controller.xenditModel.value.enable == true, + child: cardDecoration( + controller, + PaymentGateway.xendit, + isDark, + "assets/images/xendit.png", + ), ), - Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")), ], ), ), @@ -724,48 +1587,107 @@ class RentalOrderDetailsScreen extends StatelessWidget { textColor: AppThemeData.grey900, onPress: () async { if (controller.selectedPaymentMethod.value.isEmpty) { - ShowToastDialog.showToast("Please select a payment method".tr()); + ShowToastDialog.showToast( + "Please select a payment method".tr(), + ); } else { - if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) { - controller.stripeMakePayment(amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) { - controller.paypalPaymentSheet(controller.totalAmount.value.toString(), context); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) { - controller.payStackPayment(controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) { - controller.mercadoPagoMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) { - controller.flutterWaveInitiatePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) { - controller.payFastPayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + if (controller.selectedPaymentMethod.value == + PaymentGateway.stripe.name) { + controller.stripeMakePayment( + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.paypal.name) { + controller.paypalPaymentSheet( + controller.totalAmount.value.toString(), + context, + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payStack.name) { + controller.payStackPayment( + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.mercadoPago.name) { + controller.mercadoPagoMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.flutterWave.name) { + controller.flutterWaveInitiatePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.payFast.name) { + controller.payFastPayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.cod.name) { controller.completeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) { - if (Constant.userModel!.walletAmount == null || Constant.userModel!.walletAmount! < controller.totalAmount.value) { - ShowToastDialog.showToast("You do not have sufficient wallet balance".tr()); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.wallet.name) { + if (Constant.userModel!.walletAmount == null || + Constant.userModel!.walletAmount! < + controller.totalAmount.value) { + ShowToastDialog.showToast( + "You do not have sufficient wallet balance".tr(), + ); } else { controller.completeOrder(); } - } else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) { + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.cod.name) { controller.completeOrder(); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) { - controller.midtransMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) { - controller.orangeMakePayment(context: context, amount: controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) { - controller.xenditPayment(context, controller.totalAmount.value.toString()); - } else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) { - RazorPayController().createOrderRazorPay(amount: double.parse(controller.totalAmount.value.toString()), razorpayModel: controller.razorPayModel.value).then((value) { - if (value == null) { - Get.back(); - ShowToastDialog.showToast("Something went wrong, please contact admin.".tr()); - } else { - CreateRazorPayOrderModel result = value; - controller.openCheckout(amount: controller.totalAmount.value.toString(), orderId: result.id); - } - }); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.midTrans.name) { + controller.midtransMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.orangeMoney.name) { + controller.orangeMakePayment( + context: context, + amount: controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.xendit.name) { + controller.xenditPayment( + context, + controller.totalAmount.value.toString(), + ); + } else if (controller.selectedPaymentMethod.value == + PaymentGateway.razorpay.name) { + RazorPayController() + .createOrderRazorPay( + amount: double.parse( + controller.totalAmount.value.toString(), + ), + razorpayModel: controller.razorPayModel.value, + ) + .then((value) { + if (value == null) { + Get.back(); + ShowToastDialog.showToast( + "Something went wrong, please contact admin." + .tr(), + ); + } else { + CreateRazorPayOrderModel result = value; + controller.openCheckout( + amount: controller.totalAmount.value.toString(), + orderId: result.id, + ); + } + }); } else { - ShowToastDialog.showToast("Please select payment method".tr()); + ShowToastDialog.showToast( + "Please select payment method".tr(), + ); } } }, @@ -777,7 +1699,12 @@ class RentalOrderDetailsScreen extends StatelessWidget { ); } - Obx cardDecoration(RentalOrderDetailsController controller, PaymentGateway value, isDark, String image) { + Obx cardDecoration( + RentalOrderDetailsController controller, + PaymentGateway value, + isDark, + String image, + ) { return Obx( () => Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -792,8 +1719,21 @@ class RentalOrderDetailsScreen extends StatelessWidget { Container( width: 50, height: 50, - decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))), - child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, + color: Color(0xFFE5E7EB), + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all( + value.name == "payFast" ? 0 : 8.0, + ), + child: Image.asset(image), + ), ), const SizedBox(width: 10), value.name == "wallet" @@ -804,12 +1744,30 @@ class RentalOrderDetailsScreen extends StatelessWidget { Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), Text( - Constant.amountShow(amount: Constant.userModel!.walletAmount == null ? '0.0' : Constant.userModel!.walletAmount.toString()), + Constant.amountShow( + amount: + Constant.userModel!.walletAmount == null + ? '0.0' + : Constant.userModel!.walletAmount + .toString(), + ), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300), + style: AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, + ), ), ], ), @@ -818,14 +1776,23 @@ class RentalOrderDetailsScreen extends StatelessWidget { child: Text( value.name.capitalizeString(), textAlign: TextAlign.start, - style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900), + style: AppThemeData.semiBoldTextStyle( + fontSize: 16, + color: + isDark + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), ), ), const Expanded(child: SizedBox()), Radio( value: value.name, groupValue: controller.selectedPaymentMethod.value, - activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300, + activeColor: + isDark + ? AppThemeData.primary300 + : AppThemeData.primary300, onChanged: (value) { controller.selectedPaymentMethod.value = value.toString(); }, diff --git a/lib/screen_ui/rental_service/rental_review_screen.dart b/lib/screen_ui/rental_service/rental_review_screen.dart index 486ea7a..d5fd8fb 100644 --- a/lib/screen_ui/rental_service/rental_review_screen.dart +++ b/lib/screen_ui/rental_service/rental_review_screen.dart @@ -1,7 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/constant.dart'; import '../../controllers/rental_review_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -28,11 +28,19 @@ class RentalReviewScreen extends StatelessWidget { backgroundColor: AppThemeData.primary300, leading: GestureDetector( onTap: () => Get.back(), - child: Icon(Icons.arrow_back_ios, color: isDark ? Colors.white : Colors.black), + child: Icon( + Icons.arrow_back_ios, + color: isDark ? Colors.white : Colors.black, + ), ), title: Text( - controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(), - style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 16), + controller.ratingModel.value != null + ? "Update Review".tr() + : "Add Review".tr(), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontSize: 16, + ), ), ), body: Obx( @@ -44,11 +52,21 @@ class RentalReviewScreen extends StatelessWidget { child: Stack( children: [ Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 50, bottom: 20), + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 50, + bottom: 20, + ), child: Card( elevation: 2, - color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + color: + isDark + ? AppThemeData.greyDark50 + : AppThemeData.grey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(top: 65), @@ -56,11 +74,18 @@ class RentalReviewScreen extends StatelessWidget { children: [ // Driver Name Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only( + top: 8.0, + ), child: Text( - controller.order.value!.driver?.fullName() ?? "", + controller.order.value!.driver + ?.fullName() ?? + "", style: TextStyle( - color: isDark ? Colors.white : Colors.black87, + color: + isDark + ? Colors.white + : Colors.black87, fontFamily: AppThemeData.medium, fontSize: 18, ), @@ -68,12 +93,21 @@ class RentalReviewScreen extends StatelessWidget { ), // Car info Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, children: [ Text( - controller.driverUser.value?.carNumber?.toUpperCase() ?? '', + controller + .driverUser + .value + ?.carNumber + ?.toUpperCase() ?? + '', style: TextStyle( - color: isDark ? Colors.white : Colors.black87, + color: + isDark + ? Colors.white + : Colors.black87, fontFamily: AppThemeData.medium, ), ), @@ -81,14 +115,22 @@ class RentalReviewScreen extends StatelessWidget { Text( "${controller.driverUser.value?.carName} ${controller.driverUser.value?.carMakes}", style: TextStyle( - color: isDark ? Colors.white : Colors.black38, + color: + isDark + ? Colors.white + : Colors.black38, fontFamily: AppThemeData.medium, ), ), ], ), - const Padding(padding: EdgeInsets.symmetric(vertical: 12), child: Divider(color: Colors.grey)), + const Padding( + padding: EdgeInsets.symmetric( + vertical: 12, + ), + child: Divider(color: Colors.grey), + ), // Title Padding( @@ -97,7 +139,10 @@ class RentalReviewScreen extends StatelessWidget { 'How is your trip?'.tr(), style: TextStyle( fontSize: 18, - color: isDark ? Colors.white : Colors.black, + color: + isDark + ? Colors.white + : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 2, ), @@ -106,10 +151,16 @@ class RentalReviewScreen extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 8), child: Text( - 'Your feedback will help us improve \n driving experience better'.tr(), + 'Your feedback will help us improve \n driving experience better' + .tr(), textAlign: TextAlign.center, style: TextStyle( - color: isDark ? Colors.white : Colors.black.withOpacity(0.60), + color: + isDark + ? Colors.white + : Colors.black.withOpacity( + 0.60, + ), letterSpacing: 0.8, ), ), @@ -122,7 +173,12 @@ class RentalReviewScreen extends StatelessWidget { 'Rate for'.tr(), style: TextStyle( fontSize: 16, - color: isDark ? Colors.white : Colors.black.withOpacity(0.60), + color: + isDark + ? Colors.white + : Colors.black.withOpacity( + 0.60, + ), letterSpacing: 0.8, ), ), @@ -130,10 +186,15 @@ class RentalReviewScreen extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 8), child: Text( - controller.order.value!.driver?.fullName() ?? "", + controller.order.value!.driver + ?.fullName() ?? + "", style: TextStyle( fontSize: 18, - color: isDark ? Colors.white : Colors.black, + color: + isDark + ? Colors.white + : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 2, ), @@ -142,14 +203,25 @@ class RentalReviewScreen extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 10), child: RatingBar.builder( - initialRating: controller.ratings.value, + initialRating: + controller.ratings.value, minRating: 1, direction: Axis.horizontal, allowHalfRating: true, itemCount: 5, - itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber), - unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, - onRatingUpdate: (rating) => controller.ratings.value = rating, + itemBuilder: + (context, _) => const Icon( + Icons.star, + color: Colors.amber, + ), + unratedColor: + isDark + ? AppThemeData.greyDark400 + : AppThemeData.grey400, + onRatingUpdate: + (rating) => + controller.ratings.value = + rating, ), ), @@ -167,9 +239,16 @@ class RentalReviewScreen extends StatelessWidget { Padding( padding: const EdgeInsets.all(20.0), child: RoundedButtonFill( - title: controller.ratingModel.value != null ? "Update Review" : "Add Review", + title: + controller.ratingModel.value != + null + ? "Update Review" + : "Add Review", color: AppThemeData.primary300, - textColor: isDark ? Colors.white : Colors.black, + textColor: + isDark + ? Colors.white + : Colors.black, onPress: controller.submitReview, ), ), @@ -185,12 +264,24 @@ class RentalReviewScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(60), color: Colors.white, - boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.15), blurRadius: 8, spreadRadius: 6)], + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.15), + blurRadius: 8, + spreadRadius: 6, + ), + ], ), child: ClipRRect( borderRadius: BorderRadius.circular(60), child: NetworkImageWidget( - imageUrl: controller.order.value?.driver?.profilePictureURL ?? '', + imageUrl: + controller + .order + .value + ?.driver + ?.profilePictureURL ?? + '', fit: BoxFit.cover, height: 110, width: 110, diff --git a/lib/screen_ui/service_home_screen/service_list_screen.dart b/lib/screen_ui/service_home_screen/service_list_screen.dart index c9528bb..5de8a4d 100644 --- a/lib/screen_ui/service_home_screen/service_list_screen.dart +++ b/lib/screen_ui/service_home_screen/service_list_screen.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:customer/models/section_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../controllers/service_list_controller.dart'; import '../../themes/app_them_data.dart'; import '../../utils/network_image_widget.dart'; @@ -66,7 +66,7 @@ class ServiceListScreen extends StatelessWidget { Padding( padding: EdgeInsets.symmetric(horizontal: 16.r), child: Text( - "Другие услуги", + "Other Services", style: TextStyle( fontFamily: AppThemeData.bold, fontWeight: FontWeight.w700, @@ -75,7 +75,6 @@ class ServiceListScreen extends StatelessWidget { ), ), ), - SizedBox(height: 10.h), // Other Services Section @@ -99,7 +98,6 @@ class ServiceListScreen extends StatelessWidget { title: "Продукты питания", subtitle: "Более 1000 товаров", ), - SizedBox(height: 45.h), ], ), @@ -209,7 +207,7 @@ class ServiceListScreen extends StatelessWidget { spacing: 12.r, children: [ _mainCardsMaker( - title: "Еда и доставка", + title: "Food Delivery", image: "assets/images/food_img.png", // onTap: () { // log("Main Card Tapped"); @@ -227,7 +225,7 @@ class ServiceListScreen extends StatelessWidget { // }, ), _mainCardsMaker( - title: "Курьерская доставка", + title: "Delivery", image: "assets/images/delivery_img.png", onTap: () { log("Main Card Tapped"); @@ -276,7 +274,7 @@ class ServiceListScreen extends StatelessWidget { Expanded( child: Text( maxLines: 2, - "Позвать такси", + "Booking Taxi", style: TextStyle( overflow: TextOverflow.ellipsis, fontFamily: AppThemeData.bold, diff --git a/lib/screen_ui/splash_screen/splash_screen.dart b/lib/screen_ui/splash_screen/splash_screen.dart index 652d0e0..64ef3b4 100644 --- a/lib/screen_ui/splash_screen/splash_screen.dart +++ b/lib/screen_ui/splash_screen/splash_screen.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../../constant/assets.dart'; import '../../controllers/splash_controller.dart'; import '../../themes/app_them_data.dart'; @@ -12,7 +12,12 @@ class SplashScreen extends StatelessWidget { return GetBuilder( init: SplashController(), builder: (controller) { - return Scaffold(backgroundColor: AppThemeData.surface, body: Center(child: Image.asset(AppAssets.icAppLogo, width: 120, height: 120))); + return Scaffold( + backgroundColor: AppThemeData.mainColor, + body: Center( + child: Image.asset("assets/images/fondex_logo_main.png", width: 120, height: 120), + ), + ); }, ); } diff --git a/lib/service/cart_provider.dart b/lib/service/cart_provider.dart index 4868e0a..bc2ccdb 100644 --- a/lib/service/cart_provider.dart +++ b/lib/service/cart_provider.dart @@ -5,12 +5,12 @@ import 'package:customer/models/cart_product_model.dart'; import 'package:customer/themes/custom_dialog_box.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - +import 'package:get/get.dart' hide Trans; import 'database_helper.dart'; class CartProvider with ChangeNotifier { - final _cartStreamController = StreamController>.broadcast(); + final _cartStreamController = + StreamController>.broadcast(); List _cartItems = []; Stream> get cartStream => _cartStreamController.stream; @@ -24,7 +24,11 @@ class CartProvider with ChangeNotifier { _cartStreamController.sink.add(_cartItems); } - Future addToCart(BuildContext context, CartProductModel product, int quantity) async { + Future addToCart( + BuildContext context, + CartProductModel product, + int quantity, + ) async { _cartItems = await DatabaseHelper.instance.fetchCartProducts(); if ((_cartItems.where((item) => item.id == product.id)).isNotEmpty) { var index = _cartItems.indexWhere((item) => item.id == product.id); @@ -38,7 +42,10 @@ class CartProvider with ChangeNotifier { } await DatabaseHelper.instance.updateCartProduct(_cartItems[index]); } else { - if (_cartItems.isEmpty || _cartItems.where((item) => item.vendorID == product.vendorID).isNotEmpty) { + if (_cartItems.isEmpty || + _cartItems + .where((item) => item.vendorID == product.vendorID) + .isNotEmpty) { product.quantity = quantity; _cartItems.add(product); cartItem.add(product); @@ -50,7 +57,9 @@ class CartProvider with ChangeNotifier { builder: (BuildContext context) { return CustomDialogBox( title: "Alert".tr(), - descriptions: "Your cart already contains items from another restaurant. Would you like to replace them with items from this restaurant instead?".tr(), + descriptions: + "Your cart already contains items from another restaurant. Would you like to replace them with items from this restaurant instead?" + .tr(), positiveString: "Add".tr(), negativeString: "Cancel".tr(), positiveClick: () async { diff --git a/lib/service/fire_store_utils.dart b/lib/service/fire_store_utils.dart index ad3e445..d5d0d23 100644 --- a/lib/service/fire_store_utils.dart +++ b/lib/service/fire_store_utils.dart @@ -14,7 +14,7 @@ import 'package:firebase_auth/firebase_auth.dart' as auth; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/cupertino.dart'; import 'package:geocoding/geocoding.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:intl/intl.dart'; import 'package:uuid/uuid.dart'; import 'package:video_compress/video_compress.dart'; @@ -85,7 +85,7 @@ class FireStoreUtils { static String getCurrentUid() { final user = auth.FirebaseAuth.instance.currentUser; - if(user != null){ + if (user != null) { return user.uid; } return "hello"; diff --git a/lib/service/localization_service.dart b/lib/service/localization_service.dart index b3040e7..92cfb47 100644 --- a/lib/service/localization_service.dart +++ b/lib/service/localization_service.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../lang/app_en.dart'; class LocalizationService extends Translations { diff --git a/lib/themes/custom_dialog_box.dart b/lib/themes/custom_dialog_box.dart index e2ff4d6..9b3d6da 100644 --- a/lib/themes/custom_dialog_box.dart +++ b/lib/themes/custom_dialog_box.dart @@ -1,7 +1,7 @@ import 'package:customer/themes/responsive.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../controllers/theme_controller.dart'; import 'app_them_data.dart'; @@ -29,23 +29,46 @@ class CustomDialogBox extends StatelessWidget { return Obx(() { final isDark = themeController.isDark.value; - return Dialog(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), elevation: 0, backgroundColor: Colors.transparent, child: contentBox(context, isDark)); + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context, isDark), + ); }); } Widget contentBox(BuildContext context, bool isDark) { return Container( padding: const EdgeInsets.all(20), - decoration: BoxDecoration(shape: BoxShape.rectangle, color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, borderRadius: BorderRadius.circular(20)), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100, + borderRadius: BorderRadius.circular(20), + ), child: Column( mainAxisSize: MainAxisSize.min, children: [ img ?? const SizedBox(), const SizedBox(height: 20), - if (title.isNotEmpty) Text(title.tr(), style: AppThemeData.boldTextStyle(fontSize: 20, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + if (title.isNotEmpty) + Text( + title.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 20, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), const SizedBox(height: 5), if (descriptions.isNotEmpty) - Text(descriptions.tr(), textAlign: TextAlign.center, style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), + Text( + descriptions.tr(), + textAlign: TextAlign.center, + style: AppThemeData.regularTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, + ), + ), const SizedBox(height: 20), Row( children: [ @@ -55,9 +78,25 @@ class CustomDialogBox extends StatelessWidget { child: Container( width: Responsive.width(100, context), height: Responsive.height(5, context), - decoration: BoxDecoration(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, borderRadius: BorderRadius.circular(200)), + decoration: BoxDecoration( + color: + isDark + ? AppThemeData.greyDark900 + : AppThemeData.grey900, + borderRadius: BorderRadius.circular(200), + ), child: Center( - child: Text(negativeString.tr(), textAlign: TextAlign.center, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100)), + child: Text( + negativeString.tr(), + textAlign: TextAlign.center, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: + isDark + ? AppThemeData.greyDark100 + : AppThemeData.grey100, + ), + ), ), ), ), @@ -69,8 +108,20 @@ class CustomDialogBox extends StatelessWidget { child: Container( width: Responsive.width(100, context), height: Responsive.height(5, context), - decoration: BoxDecoration(color: AppThemeData.success300, borderRadius: BorderRadius.circular(200)), - child: Center(child: Text('Confirm'.tr(), textAlign: TextAlign.center, style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.grey100))), + decoration: BoxDecoration( + color: AppThemeData.success300, + borderRadius: BorderRadius.circular(200), + ), + child: Center( + child: Text( + 'Confirm'.tr(), + textAlign: TextAlign.center, + style: AppThemeData.mediumTextStyle( + fontSize: 14, + color: AppThemeData.grey100, + ), + ), + ), ), ), ), diff --git a/lib/themes/easy_loading_config.dart b/lib/themes/easy_loading_config.dart index a48db16..6735481 100644 --- a/lib/themes/easy_loading_config.dart +++ b/lib/themes/easy_loading_config.dart @@ -1,7 +1,7 @@ import 'package:customer/themes/app_them_data.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../controllers/theme_controller.dart'; Future configEasyLoading() async { diff --git a/lib/themes/round_button_border.dart b/lib/themes/round_button_border.dart index a46e769..3b1eb2c 100644 --- a/lib/themes/round_button_border.dart +++ b/lib/themes/round_button_border.dart @@ -2,7 +2,7 @@ import 'package:customer/controllers/theme_controller.dart'; import 'package:customer/themes/responsive.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'app_them_data.dart'; class RoundedButtonBorder extends StatelessWidget { @@ -49,26 +49,51 @@ class RoundedButtonBorder extends StatelessWidget { height: Responsive.height(height ?? 6, context), decoration: ShapeDecoration( color: color ?? Colors.transparent, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius ?? 50), side: BorderSide(color: borderColor ?? AppThemeData.danger300)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius ?? 50), + side: BorderSide(color: borderColor ?? AppThemeData.danger300), + ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (isRight == false) Padding(padding: const EdgeInsets.only(right: 10, left: 0), child: icon), + if (isRight == false) + Padding( + padding: const EdgeInsets.only(right: 10, left: 0), + child: icon, + ), isCenter == true - ? Text(title.tr(), textAlign: TextAlign.center, style: AppThemeData.semiBoldTextStyle(fontSize: fontSizes ?? 14, color: textColor ?? AppThemeData.grey800)) + ? Text( + title.tr(), + textAlign: TextAlign.center, + style: AppThemeData.semiBoldTextStyle( + fontSize: fontSizes ?? 14, + color: textColor ?? AppThemeData.grey800, + ), + ) : Expanded( child: Padding( padding: EdgeInsets.only(right: isRight == null ? 0 : 30), child: Text( title.tr(), textAlign: TextAlign.center, - style: AppThemeData.semiBoldTextStyle(fontSize: fontSizes ?? 14, color: textColor ?? (isDark ? AppThemeData.grey100 : AppThemeData.grey700)), + style: AppThemeData.semiBoldTextStyle( + fontSize: fontSizes ?? 14, + color: + textColor ?? + (isDark + ? AppThemeData.grey100 + : AppThemeData.grey700), + ), ), ), ), - if (isRight == true) Padding(padding: const EdgeInsets.only(left: 10, right: 20), child: icon), + if (isRight == true) + Padding( + padding: const EdgeInsets.only(left: 10, right: 20), + child: icon, + ), ], ), ), diff --git a/lib/themes/round_button_fill.dart b/lib/themes/round_button_fill.dart index 8f61cbe..4b50524 100644 --- a/lib/themes/round_button_fill.dart +++ b/lib/themes/round_button_fill.dart @@ -1,7 +1,7 @@ import 'package:customer/themes/responsive.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'app_them_data.dart'; class RoundedButtonFill extends StatelessWidget { @@ -45,21 +45,48 @@ class RoundedButtonFill extends StatelessWidget { child: Container( width: Responsive.width(width ?? 100, context), height: Responsive.height(height ?? 6, context), - decoration: ShapeDecoration(color: color, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius ?? 50))), + decoration: ShapeDecoration( + color: color, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(borderRadius ?? 50), + ), + ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (isRight == false) Padding(padding: const EdgeInsets.only(right: 10, left: 10), child: icon), + if (isRight == false) + Padding( + padding: const EdgeInsets.only(right: 10, left: 10), + child: icon, + ), isCenter == true - ? Text(title.tr(), textAlign: TextAlign.center, style: AppThemeData.semiBoldTextStyle(fontSize: fontSizes ?? 16, color: textColor ?? AppThemeData.grey50)) + ? Text( + title.tr(), + textAlign: TextAlign.center, + style: AppThemeData.semiBoldTextStyle( + fontSize: fontSizes ?? 16, + color: textColor ?? AppThemeData.grey50, + ), + ) : Expanded( child: Padding( padding: EdgeInsets.only(right: isRight == null ? 0 : 30), - child: Text(title.tr(), textAlign: TextAlign.center, style: AppThemeData.semiBoldTextStyle(fontSize: fontSizes ?? 16, color: textColor ?? AppThemeData.grey50)), + child: Text( + title.tr(), + textAlign: TextAlign.center, + style: AppThemeData.semiBoldTextStyle( + fontSize: fontSizes ?? 16, + color: textColor ?? AppThemeData.grey50, + ), + ), ), ), - if (isRight == true) Padding(padding: const EdgeInsets.only(left: 10, right: 10), child: icon), + if (isRight == true) + Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: icon, + ), ], ), ), diff --git a/lib/themes/text_field_widget.dart b/lib/themes/text_field_widget.dart index 7e87544..44c3e57 100644 --- a/lib/themes/text_field_widget.dart +++ b/lib/themes/text_field_widget.dart @@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../controllers/theme_controller.dart'; import 'app_them_data.dart'; @@ -77,20 +77,39 @@ class _TextFieldWidgetState extends State { final themeController = Get.find(); final isDark = themeController.isDark.value; - final borderColor = widget.borderColor ?? (_focusNode.hasFocus ? (isDark ? AppThemeData.greyDark400 : AppThemeData.grey400) : (isDark ? AppThemeData.greyDark200 : AppThemeData.grey200)); + final borderColor = + widget.borderColor ?? + (_focusNode.hasFocus + ? (isDark ? AppThemeData.greyDark400 : AppThemeData.grey400) + : (isDark ? AppThemeData.greyDark200 : AppThemeData.grey200)); final fillColor = - widget.backgroundColor ?? (isDark ? (_focusNode.hasFocus ? AppThemeData.greyDark50 : AppThemeData.greyDark100) : (_focusNode.hasFocus ? AppThemeData.grey100 : Colors.transparent)); + widget.backgroundColor ?? + (isDark + ? (_focusNode.hasFocus + ? AppThemeData.greyDark50 + : AppThemeData.greyDark100) + : (_focusNode.hasFocus + ? AppThemeData.grey100 + : Colors.transparent)); final textColor = isDark ? AppThemeData.greyDark900 : AppThemeData.grey900; - final hintColor = widget.hintColor ?? (isDark ? AppThemeData.grey400 : AppThemeData.greyDark400); + final hintColor = + widget.hintColor ?? + (isDark ? AppThemeData.grey400 : AppThemeData.greyDark400); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (widget.title != null) ...[ - Text(widget.title!.tr(), style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)), + Text( + widget.title!.tr(), + style: AppThemeData.boldTextStyle( + fontSize: 14, + color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800, + ), + ), const SizedBox(height: 5), ], TextFormField( @@ -112,18 +131,46 @@ class _TextFieldWidgetState extends State { filled: true, enabled: widget.enable ?? true, fillColor: fillColor, - contentPadding: EdgeInsets.symmetric(vertical: widget.title == null ? 15 : (widget.enable == false ? 13 : 8), horizontal: 10), + contentPadding: EdgeInsets.symmetric( + vertical: + widget.title == null ? 15 : (widget.enable == false ? 13 : 8), + horizontal: 10, + ), prefixIcon: widget.prefix, suffixIcon: widget.suffix, - prefixIconConstraints: const BoxConstraints(minHeight: 20, minWidth: 20), - suffixIconConstraints: const BoxConstraints(minHeight: 20, minWidth: 20), - border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor)), - enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor)), - focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor, width: 1.2)), - errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: Colors.red)), - disabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor)), + prefixIconConstraints: const BoxConstraints( + minHeight: 20, + minWidth: 20, + ), + suffixIconConstraints: const BoxConstraints( + minHeight: 20, + minWidth: 20, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: borderColor), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: borderColor), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: borderColor, width: 1.2), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: Colors.red), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: borderColor), + ), hintText: widget.hintText.tr(), - hintStyle: AppThemeData.regularTextStyle(fontSize: 14.sp, color: hintColor), + hintStyle: AppThemeData.regularTextStyle( + fontSize: 14.sp, + color: hintColor, + ), ), ), ], diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index a7c6398..8b44e86 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -2,7 +2,7 @@ import 'package:customer/constant/constant.dart'; import 'package:customer/widget/place_picker/selected_location_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get_utils/src/extensions/internacionalization.dart'; + import 'package:map_launcher/map_launcher.dart'; import '../themes/show_toast_dialog.dart'; import 'package:geocoding/geocoding.dart'; diff --git a/lib/widget/firebase_pagination/src/widgets/defaults/empty_screen.dart b/lib/widget/firebase_pagination/src/widgets/defaults/empty_screen.dart index 844cd6d..576c3e6 100644 --- a/lib/widget/firebase_pagination/src/widgets/defaults/empty_screen.dart +++ b/lib/widget/firebase_pagination/src/widgets/defaults/empty_screen.dart @@ -1,7 +1,7 @@ // Flutter Packages import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; /// A [Widget] to show when there is no data to display. class EmptyScreen extends StatelessWidget { @@ -10,8 +10,6 @@ class EmptyScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return Center( - child: Text('Nothing found here...'.tr()), - ); + return Center(child: Text('Nothing found here...'.tr())); } } diff --git a/lib/widget/osm_map/map_controller.dart b/lib/widget/osm_map/map_controller.dart index 182b786..d08d846 100644 --- a/lib/widget/osm_map/map_controller.dart +++ b/lib/widget/osm_map/map_controller.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:customer/widget/osm_map/place_model.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:http/http.dart' as http; import '../../utils/utils.dart'; import 'package:latlong2/latlong.dart'; @@ -20,11 +20,15 @@ class OSMMapController extends GetxController { } final url = Uri.parse( - 'https://nominatim.openstreetmap.org/search?q=$query&format=json&addressdetails=1&limit=10'); + 'https://nominatim.openstreetmap.org/search?q=$query&format=json&addressdetails=1&limit=10', + ); - final response = await http.get(url, headers: { - 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', - }); + final response = await http.get( + url, + headers: { + 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', + }, + ); if (response.statusCode == 200) { final data = json.decode(response.body); @@ -52,11 +56,15 @@ class OSMMapController extends GetxController { Future _getAddressFromLatLng(LatLng coords) async { final url = Uri.parse( - 'https://nominatim.openstreetmap.org/reverse?lat=${coords.latitude}&lon=${coords.longitude}&format=json'); + 'https://nominatim.openstreetmap.org/reverse?lat=${coords.latitude}&lon=${coords.longitude}&format=json', + ); - final response = await http.get(url, headers: { - 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', - }); + final response = await http.get( + url, + headers: { + 'User-Agent': 'FlutterMapApp/1.0 (menil.siddhiinfosoft@gmail.com)', + }, + ); if (response.statusCode == 200) { final data = json.decode(response.body); @@ -79,10 +87,13 @@ class OSMMapController extends GetxController { Future getCurrentLocation() async { Position? location = await Utils.getCurrentLocation(); - LatLng latlng = - LatLng(location?.latitude ?? 0.0, location?.longitude ?? 0.0); + LatLng latlng = LatLng( + location?.latitude ?? 0.0, + location?.longitude ?? 0.0, + ); addLatLngOnly( - LatLng(location?.latitude ?? 0.0, location?.longitude ?? 0.0)); + LatLng(location?.latitude ?? 0.0, location?.longitude ?? 0.0), + ); mapController.move(latlng, mapController.camera.zoom); } } diff --git a/lib/widget/osm_map/map_picker_page.dart b/lib/widget/osm_map/map_picker_page.dart index a05628d..6b65246 100644 --- a/lib/widget/osm_map/map_picker_page.dart +++ b/lib/widget/osm_map/map_picker_page.dart @@ -7,7 +7,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:latlong2/latlong.dart'; import '../../controllers/theme_controller.dart'; diff --git a/lib/widget/permission_dialog.dart b/lib/widget/permission_dialog.dart index 701275b..e499e38 100644 --- a/lib/widget/permission_dialog.dart +++ b/lib/widget/permission_dialog.dart @@ -1,7 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import '../themes/app_them_data.dart'; import '../themes/round_button_fill.dart'; @@ -21,10 +21,15 @@ class PermissionDialog extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.add_location_alt_rounded, color: Theme.of(context).primaryColor, size: 100), + Icon( + Icons.add_location_alt_rounded, + color: Theme.of(context).primaryColor, + size: 100, + ), const SizedBox(height: 20), Text( - 'You denied location permission forever. Please allow location permission from your app settings and receive more accurate delivery.'.tr(), + 'You denied location permission forever. Please allow location permission from your app settings and receive more accurate delivery.' + .tr(), textAlign: TextAlign.center, style: TextStyle(fontSize: 18), ), @@ -34,7 +39,13 @@ class PermissionDialog extends StatelessWidget { Expanded( child: TextButton( style: TextButton.styleFrom( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30), side: BorderSide(width: 2, color: Theme.of(context).primaryColor)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + side: BorderSide( + width: 2, + color: Theme.of(context).primaryColor, + ), + ), minimumSize: const Size(1, 50), ), child: Text('close'.tr()), diff --git a/lib/widget/place_picker/location_controller.dart b/lib/widget/place_picker/location_controller.dart index c9eb0d6..70a4ab8 100644 --- a/lib/widget/place_picker/location_controller.dart +++ b/lib/widget/place_picker/location_controller.dart @@ -1,5 +1,5 @@ import 'package:customer/widget/place_picker/selected_location_model.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:geolocator/geolocator.dart'; import 'package:geocoding/geocoding.dart'; @@ -34,11 +34,15 @@ class LocationController extends GetxController { Future getCurrentLocation() async { try { - Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); + Position position = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.high, + ); selectedLocation.value = LatLng(position.latitude, position.longitude); if (mapController != null) { - mapController!.animateCamera(CameraUpdate.newLatLngZoom(selectedLocation.value!, 15)); + mapController!.animateCamera( + CameraUpdate.newLatLngZoom(selectedLocation.value!, 15), + ); } await getAddressFromLatLng(selectedLocation.value!); @@ -49,11 +53,15 @@ class LocationController extends GetxController { Future getAddressFromLatLng(LatLng latLng) async { try { - List placemarks = await placemarkFromCoordinates(latLng.latitude, latLng.longitude); + List placemarks = await placemarkFromCoordinates( + latLng.latitude, + latLng.longitude, + ); if (placemarks.isNotEmpty) { Placemark place = placemarks.first; selectedPlaceAddress.value = place; - address.value = "${place.street}, ${place.locality}, ${place.administrativeArea}, ${place.country}"; + address.value = + "${place.street}, ${place.locality}, ${place.administrativeArea}, ${place.country}"; } else { address.value = "Address not found"; } @@ -71,7 +79,10 @@ class LocationController extends GetxController { try { List locations = await locationFromAddress(zipCode); if (locations.isNotEmpty) { - selectedLocation.value = LatLng(locations.first.latitude, locations.first.longitude); + selectedLocation.value = LatLng( + locations.first.latitude, + locations.first.longitude, + ); } } catch (e) { print("Error getting coordinates for ZIP code: $e"); @@ -80,7 +91,10 @@ class LocationController extends GetxController { void confirmLocation() { if (selectedLocation.value != null) { - SelectedLocationModel selectedLocationModel = SelectedLocationModel(address: selectedPlaceAddress.value, latLng: selectedLocation.value); + SelectedLocationModel selectedLocationModel = SelectedLocationModel( + address: selectedPlaceAddress.value, + latLng: selectedLocation.value, + ); Get.back(result: selectedLocationModel); } } diff --git a/lib/widget/place_picker/location_picker_screen.dart b/lib/widget/place_picker/location_picker_screen.dart index 4c0c96d..e00f665 100644 --- a/lib/widget/place_picker/location_picker_screen.dart +++ b/lib/widget/place_picker/location_picker_screen.dart @@ -8,7 +8,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_google_places_hoc081098/flutter_google_places_hoc081098.dart'; import 'package:flutter_google_places_hoc081098/google_maps_webservice_places.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide Trans; import 'package:google_maps_flutter/google_maps_flutter.dart'; final GoogleMapsPlaces _places = GoogleMapsPlaces(apiKey: Constant.mapAPIKey); diff --git a/lib/widget/story_view/widgets/story_image.dart b/lib/widget/story_view/widgets/story_image.dart index ce6308f..9a193a5 100644 --- a/lib/widget/story_view/widgets/story_image.dart +++ b/lib/widget/story_view/widgets/story_image.dart @@ -4,8 +4,6 @@ import 'dart:ui' as ui; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; -import 'package:get/get_utils/src/extensions/internacionalization.dart'; - import '../controller/story_controller.dart'; import '../utils.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 2be1d69..f0da5ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: customer description: "A new Flutter project." -version: 1.0.0+3 +version: 1.0.0+4 environment: sdk: ^3.7.2