From 89a79276a656f6ea6b6daa604bc9abbb3a672b78 Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Tue, 20 Feb 2024 19:33:32 +0700 Subject: [PATCH 1/5] feat: new icon bottom navigation bar --- assets/icons/icon-navigation-home.png | Bin 0 -> 1189 bytes assets/icons/icon-navigation-plan.png | Bin 0 -> 1467 bytes assets/icons/icon-navigation-portfolio.png | Bin 0 -> 2341 bytes assets/icons/icon-navigation-profile.png | Bin 0 -> 2381 bytes assets/icons/icon-navigation-transaction.png | Bin 0 -> 899 bytes lib/application/assets/path_assets.dart | 5 ++ lib/features/bottom_navigation_view.dart | 58 +++++++++++-------- 7 files changed, 38 insertions(+), 25 deletions(-) create mode 100644 assets/icons/icon-navigation-home.png create mode 100644 assets/icons/icon-navigation-plan.png create mode 100644 assets/icons/icon-navigation-portfolio.png create mode 100644 assets/icons/icon-navigation-profile.png create mode 100644 assets/icons/icon-navigation-transaction.png diff --git a/assets/icons/icon-navigation-home.png b/assets/icons/icon-navigation-home.png new file mode 100644 index 0000000000000000000000000000000000000000..58dd8d7d35a8371dda1e970450c5076087a36ee0 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0vp^i9npd!3GkEk^xbi1s;*b3=BHnAk4VbcG^myAY*Zm zyA#8@b22Z19F}xPUq=Rpjs4tz5?O&2Z|i{Se&NCCcIE(#tel3 z^JSX^%UM)4{S|B&f3X}84!F-SpP_;&;rThCgEMwCObxkvM?_2~A|zSK(dxSOi(ZFY zFXz6jnR9zyy;H_AXW?J3w|p*4=Q>a*a~yuw4qPPMU5j8$aPrK=fLXV&Zrd1lEtuVjbf1V0Mo)PS?ehM3|Ue^aKt`G%{MPQ*9AElu`IAb@$bPuYsx! z!P-7W+7I3x$}PE`=VuZvBp}Z8Ztoqw2@OmZTdzIY!)X=h$}}Z!UViS6GL`7HeWh31 zB4Vzt+Wqu^ahp_c_VSXMiXJ!ejHWU&aWx1$y1l%4wQ!F>-zxcQ|Lqo3-FIKHns+J} z^OpDaN4`FP`>bYX06#|nn_h_8`PriB`DN8T4hn7x0?Gm%f*dJ(%3Kz*AAPRsk{>AB z8N?pEA>mi~FQt&@7j7)9XcW{I_|zKoFYo_*UzW(OB7+O}Lm$ZZy&t4$-lEjMU|PdfgM3>x%??v}@eUWMgZIC$o7TYE zvH#D3xt~=Pgfd&~N+wk=dh#?>#na_ibENFziYDLXhueO?zBWl<>bA#KZt~~PC|1n& zeRt~j@2{F~TDBBfJ9@>KGk&nP3dwfjU_bkAcS8&##}#4eY_{YUqu%W^IFE3!B(X3V zGBrvxIv{xxRd|7f;H>$F8`jk@#$J1RVYV1Ee^G&=LdwS4<>w*_cky&+U%1_Q>)}0T zj>sJECU!s8DqBv`j)0u-%AbW%!p+~0wO=`_`QmH~b8q-pj_J2Lzc%08IamAptH?Q< z9_qNunh3mhUH(e_QBFohO7x<~`ht@$NOSr>`tx!6-R%M!kL-JMF21?oV)T@brDpLC y>GA)5rpw7FJm@Q)7Hul~^B^=c%N&oqBL6}C;e&-{R`$SBg~8L+&t;ucLK6T(a^qM4 literal 0 HcmV?d00001 diff --git a/assets/icons/icon-navigation-plan.png b/assets/icons/icon-navigation-plan.png new file mode 100644 index 0000000000000000000000000000000000000000..261ac031d7ceca34b2c970528c8ae0fd27e819c5 GIT binary patch literal 1467 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 ZoHI_WD>d+w`ab{w002ovPDHLkV1n6VdWir4 literal 0 HcmV?d00001 diff --git a/lib/application/assets/path_assets.dart b/lib/application/assets/path_assets.dart index 2431f43..f6e47fa 100644 --- a/lib/application/assets/path_assets.dart +++ b/lib/application/assets/path_assets.dart @@ -49,6 +49,11 @@ class PathAssets { static const String iconTicket = 'assets/icons/icon-ticket.png'; static const String iconGadget = 'assets/icons/icon-gadget.png'; static const String iconCar = 'assets/icons/icon-car.png'; + static const String iconNavigationHome = 'assets/icons/icon-navigation-home.png'; + static const String iconNavigationPlan = 'assets/icons/icon-navigation-plan.png'; + static const String iconNavigationTransaction = 'assets/icons/icon-navigation-transaction.png'; + static const String iconNavigationPortfolio = 'assets/icons/icon-navigation-portfolio.png'; + static const String iconNavigationProfile = 'assets/icons/icon-navigation-profile.png'; /// IMAGE static const String imgSplashLogo = 'assets/images/splash-logo.png'; diff --git a/lib/features/bottom_navigation_view.dart b/lib/features/bottom_navigation_view.dart index 99e24c8..2be82d5 100644 --- a/lib/features/bottom_navigation_view.dart +++ b/lib/features/bottom_navigation_view.dart @@ -1,4 +1,6 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/plan_view.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart'; @@ -6,6 +8,12 @@ import 'package:cims_apps/features/profile/view/profile_view.dart'; import 'package:cims_apps/features/transaction/view/transaction_view.dart'; import 'package:flutter/material.dart'; +class BottomNavigationItem { + String icon, label; + + BottomNavigationItem(this.icon, this.label); +} + class BottomNavigationView extends StatefulWidget { const BottomNavigationView({Key? key}) : super(key: key); @@ -26,32 +34,20 @@ class _BottomNavigationViewState extends State { ProfileView(), ]; - List listNavigation = const [ - BottomNavigationBarItem( - icon: Icon(Icons.home_outlined), - label: 'Home', - ), - BottomNavigationBarItem( - icon: Icon(Icons.file_open), - label: 'Plan', - ), - BottomNavigationBarItem( - icon: Icon(Icons.compare_arrows), - label: 'Transaction', - ), - BottomNavigationBarItem( - icon: Icon(Icons.pie_chart_rounded), - label: 'Portfolio', - ), - BottomNavigationBarItem( - icon: Icon(Icons.person), - label: 'Profile', - ), + List listNavigation = [ + BottomNavigationItem(PathAssets.iconNavigationHome, 'Home'), + BottomNavigationItem(PathAssets.iconNavigationPlan, 'Plan'), + BottomNavigationItem(PathAssets.iconNavigationTransaction, 'Transaction'), + BottomNavigationItem(PathAssets.iconNavigationPortfolio, 'Portfolio'), + BottomNavigationItem(PathAssets.iconNavigationProfile, 'Profile') ]; return Scaffold( body: listWidget[_selectedIndex], - bottomNavigationBar: Padding( + bottomNavigationBar: Container( + decoration: const BoxDecoration( + border: Border(top: BorderSide(color: ColorPalette.slate200)) + ), padding: const EdgeInsets.symmetric(vertical: 12), child: BottomNavigationBar( elevation: 0, @@ -61,13 +57,25 @@ class _BottomNavigationViewState extends State { }); }, currentIndex: _selectedIndex, - items: listNavigation, + items: listNavigation.asMap().entries.map((e) { + return BottomNavigationBarItem( + icon: Padding( + padding: const EdgeInsets.only(bottom: 4), + child: Image.asset( + e.value.icon, + width: SizeConfig.width * 0.06, + color: e.key == _selectedIndex ? ColorPalette.primary : ColorPalette.slate800 + ), + ), + label: e.value.label + ); + }).toList(), type: BottomNavigationBarType.fixed, showUnselectedLabels: true, selectedItemColor: ColorPalette.primary, unselectedItemColor: Colors.black, - selectedLabelStyle: const TextStyle(color: ColorPalette.primary), - unselectedLabelStyle: const TextStyle(color: Colors.black), + selectedLabelStyle: const TextStyle(color: ColorPalette.primary, fontSize: 12), + unselectedLabelStyle: const TextStyle(color: Colors.black, fontSize: 12), ), ), ); -- 2.45.2 From de1782c2c2dfc2ae7329508e8134c31da59bf60a Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Tue, 20 Feb 2024 19:57:52 +0700 Subject: [PATCH 2/5] fix: see more product view --- .../view/invest_type/invest_type_view.dart | 2 +- .../result_options_product.dart | 3 ++ .../view/product/view/product_view.dart | 49 ++++++++++--------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/lib/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart b/lib/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart index a33a7ac..a2f2c39 100644 --- a/lib/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart +++ b/lib/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart @@ -102,7 +102,7 @@ class _InvestTypeViewState extends State { onTap: () { provider.setSelectedProduct(e.value); routePush(context, - page: ProductView(widget.title)); + page: ProductView(selectedProduct: e.value)); }, child: Padding( padding: EdgeInsets.only( diff --git a/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart b/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart index ad54b8c..d7d7d14 100644 --- a/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart +++ b/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart @@ -3,7 +3,9 @@ import 'package:cims_apps/application/component/button/button_view.dart'; import 'package:cims_apps/application/component/image/image_view.dart'; import 'package:cims_apps/application/component/subscribe/total_payment_view.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_view.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; import 'package:flutter/material.dart'; @@ -111,6 +113,7 @@ class ResultOptionsProduct extends StatelessWidget { ), GestureDetector( onTap: () { + routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true)); }, child: const Text('See More', style: TextStyle( diff --git a/lib/features/dashboard/dashboard_account/view/product/view/product_view.dart b/lib/features/dashboard/dashboard_account/view/product/view/product_view.dart index 40438e1..9ccf953 100644 --- a/lib/features/dashboard/dashboard_account/view/product/view/product_view.dart +++ b/lib/features/dashboard/dashboard_account/view/product/view/product_view.dart @@ -24,8 +24,9 @@ class Time { } class ProductView extends StatefulWidget { - final String investType; - const ProductView(this.investType, {super.key}); + final bool seeMore; + final Product selectedProduct; + const ProductView({super.key, required this.selectedProduct, this.seeMore = false}); @override State createState() => _ProductViewState(); @@ -144,22 +145,23 @@ class _ProductViewState extends State { ], ), ), - bottomNavigationBar: Container( - height: SizeConfig.height * .1, - padding: const EdgeInsets.symmetric(horizontal: 24), - child: ButtonView( - name: 'Subscribe', - onPressed: () { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => SelectGoalInvesting(), - ); - }, - height: SizeConfig.height * 0.06, - marginVertical: 16, - ), - ), + bottomNavigationBar: !widget.seeMore ? + Container( + height: SizeConfig.height * .1, + padding: const EdgeInsets.symmetric(horizontal: 24), + child: ButtonView( + name: 'Subscribe', + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => SelectGoalInvesting(), + ); + }, + height: SizeConfig.height * 0.06, + marginVertical: 16, + ), + ) : SizedBox(), ), ); } @@ -177,7 +179,7 @@ class _ProductViewState extends State { SizedBox(width: 8), Expanded( child: Text( - 'Gemilang Dana Kas Maxima', + widget.selectedProduct.name ?? '', maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( @@ -190,17 +192,18 @@ class _ProductViewState extends State { ], ), ), + SizedBox(width: 12), Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(40), - color: ColorPalette.investTypeBgColor[widget.investType] ?? Colors.white, - border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.investType] ?? Colors.white) + color: ColorPalette.investTypeBgColor[widget.selectedProduct.type] ?? Colors.white, + border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.selectedProduct.type] ?? Colors.white) ), child: Text( - widget.investType, + widget.selectedProduct.type ?? '', style: TextStyle( - color: ColorPalette.investTypeColor[widget.investType], + color: ColorPalette.investTypeColor[widget.selectedProduct.type], fontWeight: FontWeight.w600 ), ), -- 2.45.2 From 6e03fa5fa7a72f6758ba4ac070816d2d0b6970e7 Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Wed, 21 Feb 2024 13:26:29 +0700 Subject: [PATCH 3/5] fix: validation questioner risk profile --- .../risk_profile/question_view.dart | 13 +- .../risk_profile/results_view.dart | 113 ++---------------- 2 files changed, 18 insertions(+), 108 deletions(-) diff --git a/lib/features/auth/registration/view/submission_data/risk_profile/question_view.dart b/lib/features/auth/registration/view/submission_data/risk_profile/question_view.dart index 5d38aee..e301cc8 100644 --- a/lib/features/auth/registration/view/submission_data/risk_profile/question_view.dart +++ b/lib/features/auth/registration/view/submission_data/risk_profile/question_view.dart @@ -56,17 +56,24 @@ class _QuestionViewState extends State { bottomNavigationBar: SizedBox( height: 84, child: ButtonView( + disabled: provider.listScore[currentPage] == 0, name: 'Next', marginVertical: 16, + disabledBgColor: ColorPalette.slate200, + textColor: provider.listScore[currentPage] == 0 ? ColorPalette.slate500 : Colors.white, + backgroundColor: ColorPalette.primary, onPressed: () { if (currentPage > 3) { int totalScore = provider.listScore .reduce((value, element) => value + element); provider.setTypeResult(totalScore); routePush(context, - page: ResultsView( - totalScore: totalScore.toString(), - typeResult: provider.typeResult)); + page: ResultsView( + totalScore: totalScore, + typeResult: provider.typeResult + ), + routeType: RouteType.pushReplace + ); } else { setState(() { currentPage += 1; diff --git a/lib/features/auth/registration/view/submission_data/risk_profile/results_view.dart b/lib/features/auth/registration/view/submission_data/risk_profile/results_view.dart index 80d7595..1b9129b 100644 --- a/lib/features/auth/registration/view/submission_data/risk_profile/results_view.dart +++ b/lib/features/auth/registration/view/submission_data/risk_profile/results_view.dart @@ -1,14 +1,17 @@ import 'package:cims_apps/application/component/button/back_button_view.dart'; import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/risk_profile.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/question_view.dart'; +import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view.dart'; import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart'; import 'package:cims_apps/features/auth/registration/view/submission_data/terms_and_condition/terms_and_condition_view.dart'; import 'package:flutter/material.dart'; class ResultsView extends StatelessWidget { - final String totalScore; + final int totalScore; final RiskProfileResult typeResult; const ResultsView( {super.key, required this.typeResult, required this.totalScore}); @@ -37,115 +40,15 @@ class ResultsView extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ClipRRect( - borderRadius: BorderRadius.circular(8), - child: Container( - decoration: BoxDecoration( - color: typeResult.color, - image: DecorationImage( - image: AssetImage(typeResult.img), - alignment: Alignment.centerRight)), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - typeResult.type, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 24, - color: ColorPalette.white), - ), - const SizedBox( - height: 16, - ), - const Text( - 'Total Score :', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - color: ColorPalette.white), - ), - Text( - totalScore, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 28, - color: ColorPalette.white), - ) - ], - ), - ), - ], - ), - ), - ), - const SizedBox( - height: 24, - ), - Text(typeResult.desc, - style: const TextStyle( - color: ColorPalette.slate500, fontSize: 16)), - const SizedBox( - height: 24, - ), - const Text( - 'Suitable Product', - style: TextStyle( - color: ColorPalette.slate800, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - const SizedBox( - height: 16, - ), - Wrap( - runSpacing: 16, - children: typeResult.suitableProduct.map((e) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - border: Border.all(color: ColorPalette.slate200), - ), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - alignment: Alignment.center, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: typeResult.color.withOpacity(0.1)), - child: Image.asset(e['icon'], - width: SizeConfig.width * 0.07, - color: typeResult.color)), - const SizedBox( - width: 12, - ), - Expanded( - child: Text( - e['desc'], - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: ColorPalette.slate800), - ), - ) - ], - ), - ); - }).toList(), - ), + RiskProfile(totalScore: totalScore, rowSuitableProduct: false), const SizedBox( height: 32, ), ButtonView( name: 'Re-test', - onPressed: () {}, + onPressed: () { + routePush(context, page: QuestionView(), routeType: RouteType.pushReplace); + }, marginVertical: 0, backgroundColor: ColorPalette.white, textColor: ColorPalette.primary, -- 2.45.2 From a3148d8210b4381fce914ae0bb650e479300e6f9 Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Wed, 21 Feb 2024 19:45:22 +0700 Subject: [PATCH 4/5] feat: wip redeem portfolio --- assets/icons/icon-remove.png | Bin 0 -> 1242 bytes lib/application/assets/path_assets.dart | 17 + .../component/numeric_pad/numeric_pad.dart | 10 +- lib/application/theme/color_palette.dart | 1 + .../view/portfolio/portfolio_detail_view.dart | 258 +++++++++++++ .../view/portfolio/portfolio_view.dart | 109 +++++- .../redeem_product/view/change_amount.dart | 235 ++++++++++++ .../view/change_destination_account.dart | 191 +++++++++ .../redeem_product/view/redeem_product.dart | 361 ++++++++++++++++++ .../redeem_product/view/total_redeem.dart | 151 ++++++++ .../view_model/redeem_product_view_model.dart | 64 ++++ 11 files changed, 1393 insertions(+), 4 deletions(-) create mode 100644 assets/icons/icon-remove.png create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart create mode 100644 lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart diff --git a/assets/icons/icon-remove.png b/assets/icons/icon-remove.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5b9ab7041fbe4b371a2b414e8111f49ca03fca GIT binary patch literal 1242 zcmV<01SR{4P)1^@s6;AA@~0drDELIAGL9O(c600d`2O+f$vv5yP3-dKU*xHRsW-RkNhuTiVaeBbZ{ z{fP^3!=WQ};n(lnhq_y?w_evKGbU##)79&_D)7GKvrHoh-Fpa6mB`71^Zl z@X7OogZ;gA_8+CwJW?e6ZRvTa6!lv&Eed_F3Jt*QjboYyTL|b@r_;TcO?PD@Q$!>N zGPb+5x(s%zaq={(S%yTJE#VR!2brI4qE~rgkU7Q=H4)P6t{R6&ezM;lbVGaZmu3 z4CIvbo{>UABjd;L6BK}@1JNMTBluHDbEr^(H7C~zs{FJGmI_4Eh-7O*gphY3UARJp z;zy+9s{RFJ+SIO9*A`@inh?J)^Vt9m$iQc$sL=et(2NQ3`!XE@OOSFPL5K*Y3tH2G zts3LUJ^dr&fosBsWHtgq`Dl(GBWR3*0f9szEi{GrF#$BlZSi2rv|L+QXi5WtJ~K(3 z+k(7DU?2z(iR?ssoScAm=ro6&fTn5LTv#;{o4}+}&!oU1*+wb>1rcL6o%ZC1T&k+_;pp6>0nIeY7ucy*35l|B)LjAW3z@_HNrcdRNSAu! z9~t|$o&8M+`M%c+fbhiC>uk^o?dUM}8EP29dyTBnXry+*S)t)b@6WVCgNe0s*b3zn zdr!L+dY!huwy;7k)An~jR_FzZe4%EAo|4$Nleb1F#@wZGnzp)$eV7t28qjxCrVC2$eK`Ana}qR&(Uc-%I`rwvp-Q8T7VgFQqt`R$ZrR#Ce4i&0o-6c&}vAMRjdj2@m za^hC({gq}@asK2=trwJ!%qCeHp#)&jIm*3tuN goalInvestIcon = { + 'Education': iconToga, + 'Marriage': iconCake, + 'Old age days': iconHouse, + 'Home': iconHouse, + 'Other Plan': iconCreatePlan, + 'Create Plan': iconCreatePlan, + 'Entertainment': iconTicket, + 'Gadget': iconGadget, + 'Business': iconMarket, + 'Fashion': iconBag, + 'Shop': iconBag, + 'Vehicle': iconCar, + 'Holiday': iconPlane, + }; } diff --git a/lib/application/component/numeric_pad/numeric_pad.dart b/lib/application/component/numeric_pad/numeric_pad.dart index 959d666..cbf71bf 100644 --- a/lib/application/component/numeric_pad/numeric_pad.dart +++ b/lib/application/component/numeric_pad/numeric_pad.dart @@ -1,3 +1,5 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/utils/size_config.dart'; import 'package:flutter/material.dart'; @@ -101,8 +103,9 @@ class NumericPad extends StatelessWidget { number, textAlign: TextAlign.center, style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold + fontSize: 28, + fontWeight: FontWeight.bold, + color: ColorPalette.slate800 ), ), ), @@ -117,8 +120,9 @@ class NumericPad extends StatelessWidget { onNumberSelected(''); }, child: Icon( - Icons.highlight_remove, + Icons.backspace_outlined, size: 28, + color: ColorPalette.slate800, ), ) ); diff --git a/lib/application/theme/color_palette.dart b/lib/application/theme/color_palette.dart index 992d6d5..2f4eab5 100644 --- a/lib/application/theme/color_palette.dart +++ b/lib/application/theme/color_palette.dart @@ -92,6 +92,7 @@ class ColorPalette { static const Color green100 = Color(0xFFDCFCE7); static const Color green400 = Color(0xFF4ADE80); static const Color green500 = Color(0xFF16A34A); + static const Color red600 = Color(0xffDC2626); static const Map investTypeColor = { 'Money Market': purple500, diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart new file mode 100644 index 0000000..f53f129 --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart @@ -0,0 +1,258 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/back_button_view.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PortfolioDetailView extends StatelessWidget { + const PortfolioDetailView({super.key}); + + @override + Widget build(BuildContext context) { + List listProduct = [ + PortfolioProduct( + name: 'Gemilang Dana Kas Maxima', + type: '', + yield: 8.17, + priceUnit: 2600.79, + funds: 6300000), + PortfolioProduct( + name: 'Gemilang Dana Likuid', + type: '', + yield: 6.42, + priceUnit: 1600.79, + funds: 2340000), + PortfolioProduct( + name: 'Gemilang Income Fund', + type: '', + yield: 8.17, + priceUnit: 2600.79, + funds: 6300000) + ]; + + + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (context) => RedeemProductViewModel()) + ], + child: Scaffold( + backgroundColor: Colors.white, + body: SizedBox( + width: SizeConfig.width, + height: SizeConfig.height, + child: Stack( + children: [ + const ImageView(image: PathAssets.imgDashboardAccount), + Column( + children: [ + const SizedBox( + height: 50, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const BackButtonView(), + const TextTitle(title: 'Education', color: Colors.white), + SizedBox(width: SizeConfig.width * 0.1,) + ], + ), + ), + const SizedBox(height: 24,), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Portfolio Value', + style: TextStyle( + color: ColorPalette.white, + fontWeight: FontWeight.w400 + ), + ), + TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white) + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Advantages', + style: TextStyle( + color: ColorPalette.white, + fontWeight: FontWeight.w400 + ), + ), + TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white) + ], + ) + ], + ), + ), + const SizedBox(height: 24,), + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular(0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.white, + ), + child: ListView( + padding: const EdgeInsets.all(24), + children: [ + cardPortfolio(context) + ], + ), + ), + ) + ) + ], + ) + ], + ), + ), + ), + ); + } + + Widget cardPortfolio(context) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: ColorPalette.slate200), + boxShadow: [ + BoxShadow( + color: const Color(0xff1E293B).withOpacity(0.04), + blurRadius: 8, + spreadRadius: 2 + ) + ] + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ImageView( + image: PathAssets.imgProduct, + width: SizeConfig.width * .13, + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,), + const SizedBox(height: 4), + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white, + border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white) + ), + child: Text( + 'Money Market' ?? '', + style: TextStyle( + color: ColorPalette.investTypeColor['Money Market'], + fontWeight: FontWeight.w600 + ), + ), + ) + ], + ), + ) + ], + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 16), + child: Divider(height: 1, color: ColorPalette.slate200,), + ), + Wrap( + runSpacing: 8, + children: [ + rowDescription('Present Value', 'Rp2.660.706', fontWeight: FontWeight.w700), + rowDescription('Investment Capital', 'Rp2.660.706'), + rowDescription('Advantages', 'Rp2.660.706'), + rowDescription('Purchase Price', 'Rp1.500,57'), + rowDescription('Number of Units', '14.002'), + ], + ), + const SizedBox(height: 16,), + Row( + children: [ + Expanded( + child: ButtonView( + name: 'Redeem', + marginVertical: 0, + width: SizeConfig.width, + isOutlined: true, + heightWrapContent: true, + contentPadding: const EdgeInsets.all(12), + backgroundColor: Colors.white, + borderColor: ColorPalette.red600, + textColor: ColorPalette.red600, + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return RedeemProduct(); + }, + ); + }, + ), + ), + const SizedBox(width: 16), + Expanded( + child: ButtonView( + name: 'Buy', + marginVertical: 0, + width: SizeConfig.width, + heightWrapContent: true, + contentPadding: const EdgeInsets.all(12), + onPressed: () { + + }, + ), + ) + ], + ) + ], + ), + ); + } + + Widget rowDescription(String title, String value, {Color? color, FontWeight? fontWeight}) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(title, + style: const TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w600 + ), + ), + Text(value, + style: TextStyle( + color: color ?? ColorPalette.slate800, + fontWeight: fontWeight ?? FontWeight.w600, + ), + ) + ], + ); + } +} diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart index ab4915c..2e5c504 100644 --- a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart +++ b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart @@ -1,7 +1,10 @@ import 'package:cims_apps/application/assets/path_assets.dart'; import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; @@ -147,9 +150,31 @@ class _PortofolioViewState extends State { ), menuPortofolio(), const SizedBox( - height: 24, + height: 12, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextTitle(title: 'My Portfolio', fontSize: 16), + Row( + children: [ + Icon(Icons.add, size: 18, color: ColorPalette.primary), + SizedBox(width: 4), + Text('Create', + style: TextStyle( + color: ColorPalette.primary, + fontWeight: FontWeight.w600 + ), + ) + ], + ) + ], + ), ), ...listColumnPortofolio(), + cardPortfolio() ], ), ), @@ -183,6 +208,7 @@ class _PortofolioViewState extends State { seePortofolioValue ? Icons.visibility_off_outlined : Icons.visibility_outlined, + size: 18, color: const Color(0xff93C5FD))) ], ), @@ -358,4 +384,85 @@ class _PortofolioViewState extends State { ); }).toList(); } + + Widget cardPortfolio() { + return GestureDetector( + onTap: () { + routePush(context, page: PortfolioDetailView()); + }, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 24), + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + border: Border.all(color: ColorPalette.slate200) + ), + child: Column( + children: [ + Row( + children: [ + Container( + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: ColorPalette.blue200.withOpacity(0.5), + borderRadius: BorderRadius.circular(8) + ), + child: ImageView( + image: PathAssets.goalInvestIcon['Education'], + width: SizeConfig.width * 0.07 + ) + ), + SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextTitle(title: 'Education', fontSize: 16,), + Text('2 Subscriptions', + style: TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w600 + ), + ) + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Divider(height: 1, color: ColorPalette.slate200), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Portfolio Value', + style: TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w400 + ), + ), + TextTitle(title: 'Rp 2.000.000', fontSize: 14,) + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Advantages', + style: TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w400 + ), + ), + TextTitle(title: 'Rp 2.000.000', fontSize: 14) + ], + ) + ], + ) + ], + ), + ), + ); + } } diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart new file mode 100644 index 0000000..e5d5a0a --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart @@ -0,0 +1,235 @@ +import 'dart:math'; + +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/number_formatter.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ChangeAmount extends StatefulWidget { + final int totalAmount; + const ChangeAmount({super.key, required this.totalAmount}); + + @override + State createState() => _ChangeAmountState(); +} + +class _ChangeAmountState extends State { + TextEditingController amountController = TextEditingController(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + amountController.text = NumberFormatter.numberCurrency(widget.totalAmount, 'Rp ', 'id_ID', decimalDigits: 0); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + amountController.dispose(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => RedeemProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return const RedeemProduct(); + }, + ); + }, + child: const Icon(Icons.arrow_back_rounded) + ), + const Text('Type amount', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 16, + color: ColorPalette.slate800 + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: const Icon(Icons.close_rounded) + ) + ], + ), + ), + const Divider(height: 1, color: ColorPalette.slate200,), + Padding( + padding: EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + cardProduct(), + SizedBox(height: 24), + TextField( + controller: amountController, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w600, + color: ColorPalette.slate800 + ), + keyboardType: TextInputType.number, + onChanged: (value) { + value = value.replaceAll('Rp ', '').replaceAll('.', ''); + double parseValue = double.parse(value); + if(value.isNotEmpty){ + amountController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0); + }else{ + amountController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0); + } + }, + decoration: const InputDecoration( + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: ColorPalette.primary, + width: 2 + ), + ) + ), + ), + SizedBox(height: 12), + Text( + 'Min Redeem: ${(NumberFormatter.numberCurrency(10000, 'Rp ', 'id_ID', decimalDigits: 0))}', + style: TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w600, + ), + ), + Text( + 'Max Redeem: ${(NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0))}', + style: TextStyle( + color: ColorPalette.slate400, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 24), + NumericPad(onNumberSelected: (p0) { + String checkIsZeroInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', ''); + String getNumeric = p0; + + if(p0.isNotEmpty){ + if(checkIsZeroInput != '0'){ + getNumeric = checkIsZeroInput + getNumeric; + } + }else{ + getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1); + } + if(getNumeric.isEmpty){ + getNumeric = '0'; + } + if(double.parse(getNumeric) >= provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!){ + getNumeric = (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toString(); + } + String formatNumeric = NumberFormatter.numberCurrency( + double.parse(getNumeric).toInt(), 'Rp ', 'id_ID', decimalDigits: 0); + amountController.text = formatNumeric; + }), + const SizedBox(height: 24), + ButtonView( + name: 'Confirm', + textSize: 20, + marginVertical: 0, + onPressed: () { + String formatValueInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', ''); + provider.setAmount(double.parse(formatValueInput)); + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return const RedeemProduct(); + }, + ); + }, + ) + ], + ), + ) + ], + ); + } + ), + ); + } + + Widget cardProduct() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: ColorPalette.slate200), + boxShadow: [ + BoxShadow( + color: const Color(0xff1E293B).withOpacity(0.04), + blurRadius: 8, + spreadRadius: 2 + ) + ] + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ImageView( + image: PathAssets.imgProduct, + width: SizeConfig.width * .13, + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,), + const SizedBox(height: 4), + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white, + border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white) + ), + child: Text( + 'Money Market' ?? '', + style: TextStyle( + color: ColorPalette.investTypeColor['Money Market'], + fontWeight: FontWeight.w600 + ), + ), + ) + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart new file mode 100644 index 0000000..71ca1c5 --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart @@ -0,0 +1,191 @@ +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ChangeDestinationAccount extends StatelessWidget { + const ChangeDestinationAccount({super.key}); + + @override + Widget build(BuildContext context) { + List listAccount = [ + Account('Muhamad Rosyidin', 'BRI', '902139012324'), + Account('Achmad Muhaimin', 'BCA', '21391283928') + ]; + + return ChangeNotifierProvider( + create: (context) => RedeemProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return const RedeemProduct(); + }, + ); + }, + child: const Icon(Icons.arrow_back_rounded) + ), + const Text('Change Destination Account', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 16, + color: ColorPalette.slate800 + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: const Icon(Icons.close_rounded) + ) + ], + ), + ), + const Divider(height: 1, color: ColorPalette.slate200,), + Padding( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + ...listAccount.asMap().entries.map((e) { + return GestureDetector( + onTap: () => provider.setSelectedAcc(e.value), + child: Padding( + padding: EdgeInsets.only(top: e.key != 0 ? 16 : 0), + child: cardAccount(e.value, provider.selectedAccount?.number ?? provider.getCurrentAccount.number), + ), + ); + }), + const SizedBox(height: 24), + GestureDetector( + child: const Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.add, size: 24, color: ColorPalette.primary), + SizedBox(width: 12,), + Text('New Bank', + style: TextStyle( + color: ColorPalette.primary, + fontSize: 20, + fontWeight: FontWeight.w600 + ), + ) + ], + ), + ), + const SizedBox(height: 32), + ButtonView( + name: 'Save', + textSize: 20, + marginVertical: 0, + onPressed: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + provider.setCurrentAcc(provider.selectedAccount!); + return const RedeemProduct(); + }, + ); + }, + ) + ], + ), + ), + ], + ); + } + ), + ); + } + + Widget cardAccount(Account account, String numberSelected) { + List listNumber = []; + + List.generate(account.number.length, (index) { + if(index > 3 && index < account.number.length - 4){ + listNumber.add('*'); + }else{ + listNumber.add(account.number[index]); + } + }); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + border: Border.all(color: ColorPalette.slate200) + ), + child: Row( + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(account.nameOwner, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate800 + ), + ), + Text( + '${account.nameBank} - ${listNumber.join("")}', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate400 + ), + ) + ], + ), + ], + ), + ), + AnimatedContainer( + margin: const EdgeInsets.only(top: 4), + duration: const Duration(milliseconds: 200), + height: 16, + width: 16, + padding: const EdgeInsets.all(1), + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: numberSelected == account.number + ? ColorPalette.primary + : ColorPalette.slate200)), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + child: Container( + decoration: BoxDecoration( + color: + numberSelected == account.number ? ColorPalette.primary : ColorPalette.white, + shape: BoxShape.circle), + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart new file mode 100644 index 0000000..57e2a43 --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart @@ -0,0 +1,361 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/number_formatter.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class RedeemProduct extends StatefulWidget { + const RedeemProduct({super.key}); + + @override + State createState() => _RedeemProductState(); +} + +class _RedeemProductState extends State { + TextEditingController amountController = TextEditingController(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + amountController.dispose(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => RedeemProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + double amount = provider.getAmount ?? provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!; + amountController.text = NumberFormatter.numberCurrency(amount.toInt(), 'Rp ', 'id_ID', decimalDigits: 0); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('Products to be Redeemed', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate800, + fontSize: 16 + ), + ), + GestureDetector( + onTap: () => Navigator.pop(context), + child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,) + ) + ], + ), + ), + const Divider(height: 1, color: ColorPalette.slate200,), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + cardProduct(), + const SizedBox(height: 16), + segmentAmount( + context, + provider.getAmount ?? provider.getCurrentProduct.priceUnit! * (provider.getCurrentProduct.totalUnit! / 2.0), + provider.getUnit ?? provider.getCurrentProduct.totalUnit! / 2.0, + (value) { + provider.setUnit(value); + }, + ), + const SizedBox(height: 16), + segmentDestinationAcc(provider.getCurrentAccount), + const SizedBox(height: 36), + ButtonView( + name: 'Redeem', + textSize: 20, + marginVertical: 0, + onPressed: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return TotalRedeem(); + }, + ); + }, + ), + const SizedBox(height: 16) + ], + ), + ) + ], + ); + } + ), + ); + } + + Widget cardProduct() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: ColorPalette.slate200), + boxShadow: [ + BoxShadow( + color: const Color(0xff1E293B).withOpacity(0.04), + blurRadius: 8, + spreadRadius: 2 + ) + ] + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ImageView( + image: PathAssets.imgProduct, + width: SizeConfig.width * .13, + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,), + const SizedBox(height: 4), + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white, + border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white) + ), + child: Text( + 'Money Market' ?? '', + style: TextStyle( + color: ColorPalette.investTypeColor['Money Market'], + fontWeight: FontWeight.w600 + ), + ), + ) + ], + ), + ) + ], + ), + ); + } + + Widget segmentAmount(context, double currentAmount, double currentUnit, void Function(double value) setUnit) { + double sliderValue = currentUnit / Provider.of(context, listen: false).getCurrentProduct.totalUnit!; + return Column( + children: [ + const Align( + alignment: Alignment.centerLeft, + child: Text('Amount', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate800, + fontSize: 16 + ), + ), + ), + TextField( + controller: amountController, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w700, + color: ColorPalette.slate800 + ), + keyboardType: TextInputType.number, + readOnly: true, + decoration: InputDecoration( + enabledBorder: const UnderlineInputBorder( + borderSide: BorderSide( + color: ColorPalette.slate200, + width: 1 + ), + ), + suffixIcon: GestureDetector( + onTap: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return ChangeAmount( + totalAmount: currentAmount.toInt(), + ); + }, + ); + }, + child: const Icon(Icons.edit, color: ColorPalette.primary), + ) + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','), + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 18, + color: ColorPalette.slate800 + ), + ), + const Text(' unit', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate400 + ), + ) + ], + ), + ), + Row( + children: [ + Expanded( + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + trackHeight: 4.0, + thumbColor: ColorPalette.primary, + thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10.0), + overlayColor:Colors.deepPurple, + inactiveTickMarkColor: ColorPalette.primary, + inactiveTrackColor: ColorPalette.slate200, + overlayShape: SliderComponentShape.noOverlay + ), + child: Slider( + value: sliderValue, + onChanged: setUnit, + label: sliderValue.round().toString(), + ), + ), + ), + SizedBox(width: 12), + Text('${(sliderValue * 100).toStringAsFixed(2)} %', + style: const TextStyle( + color: ColorPalette.slate800, + fontWeight: FontWeight.w600 + ), + ) + ], + ) + ], + ); + } + + Widget segmentDestinationAcc(Account account) { + List listNumber = []; + + List.generate(account.number.length, (index) { + if(index > 3 && index < account.number.length - 4){ + listNumber.add('*'); + }else{ + listNumber.add(account.number[index]); + } + }); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Destination Account', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate800, + fontSize: 16 + ), + ), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + border: Border.all(color: ColorPalette.slate200) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(account.nameOwner, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate800 + ), + ), + Text('${account.nameBank} - ${listNumber.join("")}', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate400 + ), + ) + ], + ), + ], + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => const ChangeDestinationAccount(), + ); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(18), + color: ColorPalette.blue200.withOpacity(0.5) + ), + child: const Row( + children: [ + Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20), + SizedBox(width: 4), + Text('Change', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.primary + ), + ) + ], + ), + ), + ) + ], + ), + ) + ], + ); + } +} diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart new file mode 100644 index 0000000..bfbae8e --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart @@ -0,0 +1,151 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class TotalRedeem extends StatelessWidget { + const TotalRedeem({super.key}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => RedeemProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Investment Funds that You Cash Out', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate800, + fontSize: 16 + ), + ), + GestureDetector( + onTap: () => Navigator.pop(context), + child: Icon(Icons.close_rounded, color: ColorPalette.slate800,) + ) + ], + ), + ), + Divider(height: 1, color: ColorPalette.slate200,), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: cardProduct(provider.getCurrentProduct, provider.getUnit!), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Sales Commission', + style: TextStyle( + color: ColorPalette.slate400, + fontSize: 16 + ), + ), + Text('Free', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.primary, + fontSize: 16 + ), + ) + ], + ), + ), + SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Cash Out Method', + style: TextStyle( + color: ColorPalette.slate400, + fontSize: 16 + ), + ), + Text('Regular', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.primary, + fontSize: 16 + ), + ) + ], + ), + ), + SizedBox(height: 16,), + + ], + ); + } + ), + ); + } + + Widget cardProduct(PortfolioProduct product, double currentUnit) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: ColorPalette.slate200), + boxShadow: [ + BoxShadow( + color: const Color(0xff1E293B).withOpacity(0.04), + blurRadius: 8, + spreadRadius: 2 + ) + ] + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ImageView( + image: PathAssets.imgProduct, + width: SizeConfig.width * .13, + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextTitle(title: product.name ?? '', fontSize: 16,), + const SizedBox(height: 4), + Row( + children: [ + Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','), + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 18, + color: ColorPalette.slate800 + ), + ), + const Text(' unit', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate400 + ), + ) + ], + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart new file mode 100644 index 0000000..77147d6 --- /dev/null +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; + +class Account { + String nameOwner, nameBank, number; + + Account(this.nameOwner, this.nameBank, this.number); +} + +class PortfolioProduct { + String? name, type; + double? yield; + double? priceUnit, funds, totalPercent, totalUnit; + + PortfolioProduct({this.name, this.type, this.yield, this.priceUnit, this.funds, this.totalPercent = 1, this.totalUnit}); +} + +class RedeemProductViewModel extends ChangeNotifier { + static Account currentAccount = Account('Muhamad Rosyidin', 'BRI', '902139012324'); + static PortfolioProduct currentProduct = + PortfolioProduct( + name: 'Gemilang Dana Kas Maxima', + type: '', + yield: 8.17, + priceUnit: 2600.79, + funds: 6300000, + totalUnit: 25 + ); + + static double? amount; + static double? unit; + Account? selectedAccount; + + Account get getCurrentAccount => currentAccount; + PortfolioProduct get getCurrentProduct => currentProduct; + double? get getAmount => amount; + double? get getUnit => unit; + + void setCurrentAcc(Account account) { + currentAccount = account; + notifyListeners(); + } + + void setSelectedAcc(Account account){ + selectedAccount = account; + notifyListeners(); + } + + void setAmount(double amount) { + amount = amount; + unit = (amount / currentProduct.priceUnit!); + notifyListeners(); + } + + void setUnit(double value){ + unit = currentProduct.totalUnit! * value; + amount = unit! * currentProduct.priceUnit!; + notifyListeners(); + } + + void setProduct(PortfolioProduct product) { + currentProduct = product; + notifyListeners(); + } +} \ No newline at end of file -- 2.45.2 From 176261923da0d02ca517fb22eff2756b54652e85 Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Thu, 22 Feb 2024 14:43:40 +0700 Subject: [PATCH 5/5] fix: provider view model agreement redeem and product --- .../custom_app_bar/custom_app_bar.dart | 2 +- .../component/radio_agreement.dart | 73 +++++ .../subscribe/goal_investing_view.dart | 4 +- .../subscribe/input_investment_view.dart | 1 - .../component/subscribe/other_plan_view.dart | 12 +- .../subscribe/total_payment_view.dart | 167 +++++------ .../view/plan/view/plan_view.dart | 78 ++--- .../result_options_product.dart | 269 ++++++++++-------- .../view/plan/view_model/plan_view_model.dart | 6 + .../view/portfolio/portfolio_view.dart | 26 +- .../redeem_product/view/total_redeem.dart | 74 ++++- .../view_model/redeem_product_view_model.dart | 7 + .../step_subscribe/select_goal_investing.dart | 58 ++-- .../view_model/product_view_model.dart | 6 + lib/features/profile/view/profile_view.dart | 2 +- .../transaction/view/transaction_view.dart | 3 +- 16 files changed, 501 insertions(+), 287 deletions(-) create mode 100644 lib/application/component/radio_agreement.dart diff --git a/lib/application/component/custom_app_bar/custom_app_bar.dart b/lib/application/component/custom_app_bar/custom_app_bar.dart index 727455e..a119939 100644 --- a/lib/application/component/custom_app_bar/custom_app_bar.dart +++ b/lib/application/component/custom_app_bar/custom_app_bar.dart @@ -11,9 +11,9 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { const CustomAppBar({ Key? key, required this.height, - this.leading, required this.title, this.trailing, + this.leading, }) : super(key: key); @override diff --git a/lib/application/component/radio_agreement.dart b/lib/application/component/radio_agreement.dart new file mode 100644 index 0000000..cecd678 --- /dev/null +++ b/lib/application/component/radio_agreement.dart @@ -0,0 +1,73 @@ +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:flutter/material.dart'; + +class RadioAgreement extends StatelessWidget { + final void Function() onTap; + final bool isAgree; + final String desc; + const RadioAgreement({super.key, required this.isAgree, required this.desc, required this.onTap,}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: onTap, + child: AnimatedContainer( + margin: const EdgeInsets.only(top: 4), + duration: const Duration(milliseconds: 200), + height: 16, + width: 16, + padding: const EdgeInsets.all(1), + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: isAgree + ? ColorPalette.primary + : ColorPalette.slate200)), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + child: Container( + decoration: BoxDecoration( + color: + isAgree ? ColorPalette.primary : ColorPalette.white, + shape: BoxShape.circle), + ), + ), + ), + ), + const SizedBox( + width: 12, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + desc, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate400), + ), + GestureDetector( + onTap: () {}, + child: const Text( + 'Read More', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + decoration: TextDecoration.underline, + color: ColorPalette.primary), + )) + ], + )) + ], + ), + ); + } +} diff --git a/lib/application/component/subscribe/goal_investing_view.dart b/lib/application/component/subscribe/goal_investing_view.dart index 80c3e53..7c047fd 100644 --- a/lib/application/component/subscribe/goal_investing_view.dart +++ b/lib/application/component/subscribe/goal_investing_view.dart @@ -36,8 +36,8 @@ class GoalInvestingView extends StatelessWidget { routePush( context, page: OtherPlanView( - selectedPlan: (value) { - onListSelected(e.value.title); + selectedPlan: (val) { + onListSelected(val); }, ) ); diff --git a/lib/application/component/subscribe/input_investment_view.dart b/lib/application/component/subscribe/input_investment_view.dart index 846a057..1dd8a22 100644 --- a/lib/application/component/subscribe/input_investment_view.dart +++ b/lib/application/component/subscribe/input_investment_view.dart @@ -54,7 +54,6 @@ class _InputInvestmentViewState extends State { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w700, - ), ), Row( diff --git a/lib/application/component/subscribe/other_plan_view.dart b/lib/application/component/subscribe/other_plan_view.dart index 60bff7a..55204b5 100644 --- a/lib/application/component/subscribe/other_plan_view.dart +++ b/lib/application/component/subscribe/other_plan_view.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:cims_apps/application/assets/path_assets.dart'; import 'package:cims_apps/application/component/button/button_view.dart'; import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; @@ -72,6 +74,8 @@ class _OtherPlanViewState extends State { disabled: !(selectedPlan.img != ''), onPressed: () { Navigator.pop(context); + print('haloo'); + print(selectedPlan.name); widget.selectedPlan(selectedPlan.name); }, heightWrapContent: true, @@ -91,6 +95,7 @@ class _OtherPlanViewState extends State { if(plan.name == 'Create Plan'){ showModalBottomSheet( context: context, + isDismissible: false, builder: (context) => modalCreatePlan(), ); } @@ -150,6 +155,9 @@ class _OtherPlanViewState extends State { GestureDetector( onTap: () { Navigator.pop(context); + setState(() { + selectedPlan = Plan('', ''); + }); }, child: Icon(Icons.close_rounded), ) @@ -161,12 +169,12 @@ class _OtherPlanViewState extends State { ), SizedBox(height: 24), ButtonView( - name: 'Select', + name: 'Next', marginVertical: 0, disabled: !(createController.text != ''), onPressed: () { Navigator.of(context)..pop()..pop(); - widget.selectedPlan(selectedPlan.name); + widget.selectedPlan(createController.text); }, heightWrapContent: true, width: SizeConfig.width, diff --git a/lib/application/component/subscribe/total_payment_view.dart b/lib/application/component/subscribe/total_payment_view.dart index 0befdd5..a8ae096 100644 --- a/lib/application/component/subscribe/total_payment_view.dart +++ b/lib/application/component/subscribe/total_payment_view.dart @@ -1,4 +1,5 @@ import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/radio_agreement.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/number_formatter.dart'; @@ -6,22 +7,19 @@ import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; import 'package:flutter/material.dart'; -class TotalPaymentView extends StatefulWidget { +class TotalPaymentView extends StatelessWidget { final int totalInvest; final List listProduct; + final bool isAgree; + final void Function() onTapAgree; const TotalPaymentView({ super.key, required this.listProduct, required this.totalInvest, + required this.isAgree, + required this.onTapAgree, }); - @override - State createState() => _TotalPaymentViewState(); -} - -class _TotalPaymentViewState extends State { - bool isAgreement = false; - @override Widget build(BuildContext context) { return SingleChildScrollView( @@ -49,7 +47,7 @@ class _TotalPaymentViewState extends State { ], ), ), - ...widget.listProduct.asMap().entries.map((e) { + ...listProduct.asMap().entries.map((e) { return Container( padding: const EdgeInsets.only( left: 16, right: 24, bottom: 16, top: 16), @@ -75,7 +73,7 @@ class _TotalPaymentViewState extends State { flex: 7, child: Text( NumberFormatter.numberCurrency( - widget.totalInvest * e.value.totalPercent!, + totalInvest * e.value.totalPercent!, 'Rp ', 'id_ID'), textAlign: TextAlign.end, @@ -129,7 +127,7 @@ class _TotalPaymentViewState extends State { ), Text( NumberFormatter.numberCurrency( - widget.totalInvest, 'Rp ', 'id_ID'), + totalInvest, 'Rp ', 'id_ID'), textAlign: TextAlign.end, style: const TextStyle( fontWeight: FontWeight.w700, @@ -139,7 +137,14 @@ class _TotalPaymentViewState extends State { ], ), ), - buttonAgreement(), + RadioAgreement( + isAgree: isAgree, + desc: 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision. Read More', + onTap: () { + print('gagaga'); + onTapAgree(); + }, + ), Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Row( @@ -154,7 +159,7 @@ class _TotalPaymentViewState extends State { ), Text( NumberFormatter.numberCurrency( - widget.totalInvest, 'Rp ', 'id_ID'), + totalInvest, 'Rp ', 'id_ID'), textAlign: TextAlign.end, style: const TextStyle( fontWeight: FontWeight.w700, @@ -165,16 +170,16 @@ class _TotalPaymentViewState extends State { ), ), ButtonView( - disabled: !isAgreement, + disabled: !isAgree, name: 'Subscribe Now', onPressed: () { routePush(context, page: PaymentMethodView( - totalInvest: widget.totalInvest, + totalInvest: totalInvest, )); }, disabledBgColor: ColorPalette.slate200.withOpacity(0.5), - textColor: isAgreement ? Colors.white : ColorPalette.slate400, + textColor: isAgree ? Colors.white : ColorPalette.slate400, textWeight: FontWeight.w700, textSize: 20, backgroundColor: ColorPalette.primary, @@ -185,71 +190,67 @@ class _TotalPaymentViewState extends State { ); } - Widget buttonAgreement() { - bool isAgree = isAgreement; - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () { - setState(() { - isAgreement = !isAgreement; - }); - }, - child: AnimatedContainer( - margin: const EdgeInsets.only(top: 4), - duration: const Duration(milliseconds: 200), - height: 16, - width: 16, - padding: const EdgeInsets.all(1), - alignment: Alignment.center, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: isAgree - ? ColorPalette.primary - : ColorPalette.slate200)), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - child: Container( - decoration: BoxDecoration( - color: - isAgree ? ColorPalette.primary : ColorPalette.white, - shape: BoxShape.circle), - ), - ), - ), - ), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: ColorPalette.slate400), - ), - GestureDetector( - onTap: () {}, - child: const Text( - 'Read More', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - decoration: TextDecoration.underline, - color: ColorPalette.primary), - )) - ], - )) - ], - ), - ); - } + // Widget buttonAgreement() { + // return Padding( + // padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // GestureDetector( + // onTap: () { + // }, + // child: AnimatedContainer( + // margin: const EdgeInsets.only(top: 4), + // duration: const Duration(milliseconds: 200), + // height: 16, + // width: 16, + // padding: const EdgeInsets.all(1), + // alignment: Alignment.center, + // decoration: BoxDecoration( + // shape: BoxShape.circle, + // border: Border.all( + // color: isAgree + // ? ColorPalette.primary + // : ColorPalette.slate200)), + // child: AnimatedContainer( + // duration: const Duration(milliseconds: 200), + // child: Container( + // decoration: BoxDecoration( + // color: + // isAgree ? ColorPalette.primary : ColorPalette.white, + // shape: BoxShape.circle), + // ), + // ), + // ), + // ), + // const SizedBox( + // width: 12, + // ), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Text( + // 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.', + // style: TextStyle( + // fontSize: 16, + // fontWeight: FontWeight.w600, + // color: ColorPalette.slate400), + // ), + // GestureDetector( + // onTap: () {}, + // child: const Text( + // 'Read More', + // style: TextStyle( + // fontSize: 16, + // fontWeight: FontWeight.w600, + // decoration: TextDecoration.underline, + // color: ColorPalette.primary), + // )) + // ], + // )) + // ], + // ), + // ); + // } } diff --git a/lib/features/dashboard/dashboard_account/view/plan/view/plan_view.dart b/lib/features/dashboard/dashboard_account/view/plan/view/plan_view.dart index 664a044..b373824 100644 --- a/lib/features/dashboard/dashboard_account/view/plan/view/plan_view.dart +++ b/lib/features/dashboard/dashboard_account/view/plan/view/plan_view.dart @@ -40,42 +40,50 @@ class _PlanViewState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(height: 70, title: 'Investment Plan'), - body: SingleChildScrollView( - padding: EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RiskProfile( - totalScore: 26, - rowSuitableProduct: true - ), - SizedBox( - height: 32, - ), - Text('Your Goal in Investing', - style: TextStyle( - fontWeight: FontWeight.w700, - color: ColorPalette.slate800, - fontSize: 18 + return ChangeNotifierProvider( + create: (context) => PlanViewModel(), + child: Scaffold( + appBar: CustomAppBar( + height: SizeConfig.height * 0.08, + title: 'Investment Plan', + leading: SizedBox(), + ), + body: SingleChildScrollView( + padding: EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RiskProfile( + totalScore: 26, + rowSuitableProduct: true ), - ), - SizedBox( - height: 24, - ), - GoalInvestingView( - onListSelected: (p0) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) { - return modalInvest(context, p0); - }, - ); - }, - ) - ], + SizedBox( + height: 32, + ), + Text('Your Goal in Investing', + style: TextStyle( + fontWeight: FontWeight.w700, + color: ColorPalette.slate800, + fontSize: 18 + ), + ), + SizedBox( + height: 24, + ), + GoalInvestingView( + onListSelected: (p0) { + print(p0); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return modalInvest(context, p0); + }, + ); + }, + ) + ], + ), ), ), ); diff --git a/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart b/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart index d7d7d14..04deffc 100644 --- a/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart +++ b/lib/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart @@ -5,9 +5,12 @@ import 'package:cims_apps/application/component/subscribe/total_payment_view.dar import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/options_starting_invest.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_view.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class ResultOptionsProduct extends StatelessWidget { final int totalInvest; @@ -21,135 +24,169 @@ class ResultOptionsProduct extends StatelessWidget { Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1) ]; - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16) - ), - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Icon(Icons.arrow_back, color: ColorPalette.slate500), - Text('Results from your risk profile', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 18, - color: ColorPalette.slate800 - ), - ), - Icon(Icons.close_rounded, color: ColorPalette.slate400) - ], - ), - const SizedBox(height: 32), - SingleChildScrollView( + return ChangeNotifierProvider( + create: (context) => PlanViewModel(), + child: Consumer( + builder: (context, provider, child) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16) + ), + padding: const EdgeInsets.all(24), child: Column( - children: listProduct.asMap().entries.map((e) { - return Container( - margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: ColorPalette.slate200), - borderRadius: BorderRadius.circular(12), - boxShadow: const [ - BoxShadow( - color: Color(0XFF1E293B0A) - ) - ] - ), + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + builder: (context) { + return OptionsStartingInvest(totalInvest: totalInvest); + }, + ); + }, + child: Icon(Icons.arrow_back, color: ColorPalette.slate500) + ), + Text('Results from your risk profile', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 18, + color: ColorPalette.slate800 + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + + }, + child: Icon(Icons.close_rounded, color: ColorPalette.slate400) + ) + ], + ), + const SizedBox(height: 32), + SingleChildScrollView( child: Column( - children: [ - Row( - children: [ - const ImageView(image: PathAssets.iconGoogle, width: 30,), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + children: listProduct.asMap().entries.map((e) { + return Container( + margin: const EdgeInsets.only(bottom: 16), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: ColorPalette.slate200), + borderRadius: BorderRadius.circular(12), + boxShadow: const [ + BoxShadow( + color: Color(0XFF1E293B0A) + ) + ] + ), + child: Column( + children: [ + Row( children: [ - Text(e.value.name ?? '', - style: const TextStyle( - fontWeight: FontWeight.w700, - color: ColorPalette.slate800, + const ImageView(image: PathAssets.iconGoogle, width: 30,), + const SizedBox( + width: 12, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(e.value.name ?? '', + style: const TextStyle( + fontWeight: FontWeight.w700, + color: ColorPalette.slate800, + ), + ), + const SizedBox(height: 4,), + Container( + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), + decoration: BoxDecoration( + border: Border.all(color: ColorPalette.investTypeColor[e.value.type]!), + color: ColorPalette.investTypeBgColor[e.value.type], + borderRadius: BorderRadius.circular(40) + ), + child: Text(e.value.type ?? '', + style: TextStyle( + color: ColorPalette.investTypeColor[e.value.type], + fontWeight: FontWeight.w600, + fontSize: 12 + ), + ), + ) + ], ), ), - const SizedBox(height: 4,), - Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), - decoration: BoxDecoration( - border: Border.all(color: ColorPalette.investTypeColor[e.value.type]!), - color: ColorPalette.investTypeBgColor[e.value.type], - borderRadius: BorderRadius.circular(40) - ), - child: Text(e.value.type ?? '', - style: TextStyle( - color: ColorPalette.investTypeColor[e.value.type], - fontWeight: FontWeight.w600, - fontSize: 12 - ), + Text('${(e.value.totalPercent! * 100).toInt()} %', + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16, + color: ColorPalette.slate800 ), ) ], ), - ), - Text('${(e.value.totalPercent! * 100).toInt()} %', - style: const TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16, - color: ColorPalette.slate800 + const Padding( + padding: EdgeInsets.symmetric(vertical: 16), + child: Divider(height: 1, color: ColorPalette.slate200), ), - ) - ], - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 16), - child: Divider(height: 1, color: ColorPalette.slate200), - ), - GestureDetector( - onTap: () { - routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true)); - }, - child: const Text('See More', - style: TextStyle( - color: ColorPalette.slate500, - fontWeight: FontWeight.w600, - ), + GestureDetector( + onTap: () { + routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true)); + }, + child: const Text('See More', + style: TextStyle( + color: ColorPalette.slate500, + fontWeight: FontWeight.w600, + ), + ), + ) + ], ), - ) - ], + ); + }).toList(), ), - ); - }).toList(), + ), + const SizedBox( + height: 16, + ), + ButtonView( + name: 'Next', + onPressed: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => + ChangeNotifierProvider( + create: (context) => PlanViewModel(), + child: Consumer( + builder: (context, planProvider, _) { + return TotalPaymentView( + listProduct: listProduct, + totalInvest: totalInvest, + isAgree: planProvider.isAgree, + onTapAgree: planProvider.setAgree, + ); + } + ), + ) + ); + }, + width: SizeConfig.width, + heightWrapContent: true, + contentPadding: const EdgeInsets.symmetric(vertical: 16), + marginVertical: 0, + ) + ], ), - ), - const SizedBox( - height: 16, - ), - ButtonView( - name: 'Next', - onPressed: () { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => - TotalPaymentView( - listProduct: listProduct, - totalInvest: totalInvest, - ) - ); - }, - width: SizeConfig.width, - heightWrapContent: true, - contentPadding: const EdgeInsets.symmetric(vertical: 16), - marginVertical: 0, - ) - ], + ); + } ), ); } diff --git a/lib/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart b/lib/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart index 2409e63..1da05fe 100644 --- a/lib/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart +++ b/lib/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart @@ -3,4 +3,10 @@ import 'package:flutter/material.dart'; class PlanViewModel extends ChangeNotifier { List listProduct = []; + bool isAgree = false; + + void setAgree() { + isAgree = !isAgree; + notifyListeners(); + } } \ No newline at end of file diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart index 2e5c504..4d14252 100644 --- a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart +++ b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart @@ -152,8 +152,8 @@ class _PortofolioViewState extends State { const SizedBox( height: 12, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -162,7 +162,7 @@ class _PortofolioViewState extends State { children: [ Icon(Icons.add, size: 18, color: ColorPalette.primary), SizedBox(width: 4), - Text('Create', + const Text('Create', style: TextStyle( color: ColorPalette.primary, fontWeight: FontWeight.w600 @@ -173,7 +173,7 @@ class _PortofolioViewState extends State { ], ), ), - ...listColumnPortofolio(), + // ...listColumnPortofolio(), cardPortfolio() ], ), @@ -388,11 +388,11 @@ class _PortofolioViewState extends State { Widget cardPortfolio() { return GestureDetector( onTap: () { - routePush(context, page: PortfolioDetailView()); + routePush(context, page: const PortfolioDetailView()); }, child: Container( - margin: EdgeInsets.symmetric(horizontal: 24), - padding: EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), border: Border.all(color: ColorPalette.slate200) @@ -402,7 +402,7 @@ class _PortofolioViewState extends State { Row( children: [ Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: ColorPalette.blue200.withOpacity(0.5), borderRadius: BorderRadius.circular(8) @@ -412,8 +412,8 @@ class _PortofolioViewState extends State { width: SizeConfig.width * 0.07 ) ), - SizedBox(width: 8), - Column( + const SizedBox(width: 8), + const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextTitle(title: 'Education', fontSize: 16,), @@ -427,11 +427,11 @@ class _PortofolioViewState extends State { ), ], ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8), + const Padding( + padding: EdgeInsets.symmetric(vertical: 8), child: Divider(height: 1, color: ColorPalette.slate200), ), - Row( + const Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart index bfbae8e..33e6e8f 100644 --- a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart @@ -1,7 +1,10 @@ import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/radio_agreement.dart'; import 'package:cims_apps/application/component/text_title/text_title.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/number_formatter.dart'; import 'package:cims_apps/core/utils/size_config.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart'; import 'package:flutter/material.dart'; @@ -24,7 +27,7 @@ class TotalRedeem extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('Investment Funds that You Cash Out', + const Text('Investment Funds that You Cash Out', style: TextStyle( fontWeight: FontWeight.w600, color: ColorPalette.slate800, @@ -33,18 +36,18 @@ class TotalRedeem extends StatelessWidget { ), GestureDetector( onTap: () => Navigator.pop(context), - child: Icon(Icons.close_rounded, color: ColorPalette.slate800,) + child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,) ) ], ), ), - Divider(height: 1, color: ColorPalette.slate200,), + const Divider(height: 1, color: ColorPalette.slate200,), Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: cardProduct(provider.getCurrentProduct, provider.getUnit!), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 24), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -64,9 +67,9 @@ class TotalRedeem extends StatelessWidget { ], ), ), - SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + const SizedBox(height: 16), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 24), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -86,8 +89,59 @@ class TotalRedeem extends StatelessWidget { ], ), ), - SizedBox(height: 16,), - + const SizedBox(height: 16,), + Container( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), + color: ColorPalette.slate200.withOpacity(0.5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextTitle( + title: 'Estimated Funds Disbursed', + color: ColorPalette.slate500, + fontSize: 16, + ) + ), + Expanded( + child: Text( + NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0), + textAlign: TextAlign.end, + style: TextStyle( + color: ColorPalette.slate800, + fontWeight: FontWeight.w700, + fontSize: 18 + ), + ) + ) + ], + ), + ), + RadioAgreement( + isAgree: provider.isAgree, + desc: 'I agree to the sale of the mutual funds listed on this page. I understand that the total funds disbursed are approximate. The amount received may change according to the closing price of the mutual fund on the day of sale.', + onTap: provider.setAgree + ), + const SizedBox(height: 24), + ButtonView( + disabled: !provider.isAgree, + name: 'Redeem', + textSize: 20, + marginVertical: 0, + disabledBgColor: ColorPalette.slate200.withOpacity(0.5), + textColor: !provider.isAgree ? ColorPalette.slate400 : Colors.white, + onPressed: () { + Navigator.pop(context); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return TotalRedeem(); + }, + ); + }, + ), + const SizedBox(height: 24) ], ); } diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart index 77147d6..e150e1e 100644 --- a/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart +++ b/lib/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart @@ -35,6 +35,8 @@ class RedeemProductViewModel extends ChangeNotifier { double? get getAmount => amount; double? get getUnit => unit; + bool isAgree = false; + void setCurrentAcc(Account account) { currentAccount = account; notifyListeners(); @@ -61,4 +63,9 @@ class RedeemProductViewModel extends ChangeNotifier { currentProduct = product; notifyListeners(); } + + void setAgree() { + isAgree = !isAgree; + notifyListeners(); + } } \ No newline at end of file diff --git a/lib/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart b/lib/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart index 5b3d081..f21532f 100644 --- a/lib/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart +++ b/lib/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart @@ -2,6 +2,7 @@ import 'package:cims_apps/application/component/subscribe/goal_investing_view.da import 'package:cims_apps/application/component/subscribe/input_investment_view.dart'; import 'package:cims_apps/application/component/subscribe/total_payment_view.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -11,10 +12,9 @@ class SelectGoalInvesting extends StatelessWidget { @override Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (context) => ProductViewModel(),) - ], + + return ChangeNotifierProvider( + create: (context) => ProductViewModel(), child: Consumer( builder: (context, provider, child) { return Container( @@ -51,23 +51,39 @@ class SelectGoalInvesting extends StatelessWidget { context: context, isScrollControlled: true, builder: (context) { - return InputInvestmentView( - selectedPlan: p0, - nextMove: (value) { - Navigator.pop(context); - int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => - TotalPaymentView( - listProduct: [ - provider.getSelectedProduct - ], - totalInvest: formatIntParse, - ) - ); - }, + return ChangeNotifierProvider( + create: (context) => ProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + return InputInvestmentView( + selectedPlan: p0, + nextMove: (value) { + Navigator.pop(context); + int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => + ChangeNotifierProvider( + create: (context) => ProductViewModel(), + child: Consumer( + builder: (context, provider, child) { + return TotalPaymentView( + listProduct: [ + provider.getSelectedProduct + ], + totalInvest: formatIntParse, + isAgree: provider.isAgree, + onTapAgree: provider.setAgree, + ); + } + ), + ) + ); + }, + ); + } + ), ); }, ); diff --git a/lib/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart b/lib/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart index e7fddea..7835916 100644 --- a/lib/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart +++ b/lib/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart @@ -14,6 +14,7 @@ class ProductViewModel extends ChangeNotifier { Product get getSelectedProduct => selectedProduct; double totalInvestment = 0; + bool isAgree = false; void setSelectedProduct(Product product) { selectedProduct = product; @@ -24,4 +25,9 @@ class ProductViewModel extends ChangeNotifier { totalInvestment = value; notifyListeners(); } + + void setAgree() { + isAgree = !isAgree; + notifyListeners(); + } } \ No newline at end of file diff --git a/lib/features/profile/view/profile_view.dart b/lib/features/profile/view/profile_view.dart index a62fc59..fac17ac 100644 --- a/lib/features/profile/view/profile_view.dart +++ b/lib/features/profile/view/profile_view.dart @@ -8,7 +8,7 @@ class ProfileView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: CustomAppBar(height: SizeConfig.height * .1, title: 'Profile'), + appBar: CustomAppBar(height: SizeConfig.height * .08, title: 'Profile'), ); } } diff --git a/lib/features/transaction/view/transaction_view.dart b/lib/features/transaction/view/transaction_view.dart index 1059f1d..8a9b14b 100644 --- a/lib/features/transaction/view/transaction_view.dart +++ b/lib/features/transaction/view/transaction_view.dart @@ -8,8 +8,7 @@ class TransactionView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: - CustomAppBar(height: SizeConfig.height * .1, title: 'Transaction'), + appBar: CustomAppBar(height: SizeConfig.height * 0.08, title: 'Transaction'), ); } } -- 2.45.2