Compare commits
	
		
			35 Commits
		
	
	
		
			89a79276a6
			...
			bayu/dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4f2380fcdf | |||
| c23075304a | |||
| 17c7559158 | |||
| 711e5f3f52 | |||
| a99365fb0a | |||
| 41f0bb7a68 | |||
| c97130239d | |||
| 1b867227c7 | |||
| 4b07219928 | |||
| 9cdda42b8b | |||
| 6f5d3ccca8 | |||
| ff515e2621 | |||
| f057a346c2 | |||
| f84fe1017d | |||
| 27ba55314b | |||
| 59e046bd92 | |||
| 4461b78565 | |||
| f2f688f9f3 | |||
| d1adfd2ab0 | |||
| 33b2ab85e3 | |||
| 6a43a3dcaf | |||
| db1280b272 | |||
| ae4f9c25c4 | |||
| a87afe16cb | |||
| 1904e9a4a3 | |||
| d79959c47f | |||
| 38837bd4f8 | |||
| d966108e9e | |||
| 506f364b87 | |||
| 506480d812 | |||
| a6ea9a2314 | |||
| 176261923d | |||
| a3148d8210 | |||
| 6e03fa5fa7 | |||
| de1782c2c2 | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-card.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-chat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-education.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-fund.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-gadget-outline.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-home.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-logout.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-profile.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-remove.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-setting.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-shop.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/bg-profile.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.0 MiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-cat-outlined.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-empty-transaction.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-expand-purchase.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 32 KiB | 
| @@ -49,11 +49,28 @@ class PathAssets { | |||||||
|   static const String iconTicket = 'assets/icons/icon-ticket.png'; |   static const String iconTicket = 'assets/icons/icon-ticket.png'; | ||||||
|   static const String iconGadget = 'assets/icons/icon-gadget.png'; |   static const String iconGadget = 'assets/icons/icon-gadget.png'; | ||||||
|   static const String iconCar = 'assets/icons/icon-car.png'; |   static const String iconCar = 'assets/icons/icon-car.png'; | ||||||
|   static const String iconNavigationHome = 'assets/icons/icon-navigation-home.png'; |   static const String iconNavigationHome = | ||||||
|   static const String iconNavigationPlan = 'assets/icons/icon-navigation-plan.png'; |       'assets/icons/icon-navigation-home.png'; | ||||||
|   static const String iconNavigationTransaction = 'assets/icons/icon-navigation-transaction.png'; |   static const String iconNavigationPlan = | ||||||
|   static const String iconNavigationPortfolio = 'assets/icons/icon-navigation-portfolio.png'; |       'assets/icons/icon-navigation-plan.png'; | ||||||
|   static const String iconNavigationProfile = 'assets/icons/icon-navigation-profile.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'; | ||||||
|  |   static const String iconRemove = 'assets/icons/icon-remove.png'; | ||||||
|  |   static const String iconEducation = 'assets/icons/icon-education.png'; | ||||||
|  |   static const String iconFund = 'assets/icons/icon-fund.png'; | ||||||
|  |   static const String iconHome = 'assets/icons/icon-home.png'; | ||||||
|  |   static const String iconShop = 'assets/icons/icon-shop.png'; | ||||||
|  |   static const String iconCard = 'assets/icons/icon-card.png'; | ||||||
|  |   static const String iconChat = 'assets/icons/icon-chat.png'; | ||||||
|  |   static const String iconLogout = 'assets/icons/icon-logout.png'; | ||||||
|  |   static const String iconProfile = 'assets/icons/icon-profile.png'; | ||||||
|  |   static const String iconSetting = 'assets/icons/icon-setting.png'; | ||||||
|  |   static const String iconGadgetOutline = | ||||||
|  |       'assets/icons/icon-gadget-outline.png'; | ||||||
|  |  | ||||||
|   /// IMAGE |   /// IMAGE | ||||||
|   static const String imgSplashLogo = 'assets/images/splash-logo.png'; |   static const String imgSplashLogo = 'assets/images/splash-logo.png'; | ||||||
| @@ -82,13 +99,36 @@ class PathAssets { | |||||||
|   static const String imgMoneyIncome = 'assets/images/img-money-income.png'; |   static const String imgMoneyIncome = 'assets/images/img-money-income.png'; | ||||||
|   static const String imgGrowing = 'assets/images/img-growing.png'; |   static const String imgGrowing = 'assets/images/img-growing.png'; | ||||||
|   static const String imgCat = 'assets/images/img-cat.png'; |   static const String imgCat = 'assets/images/img-cat.png'; | ||||||
|  |   static const String imgCatOutlined = 'assets/images/img-cat-outlined.png'; | ||||||
|   static const String imgDeer = 'assets/images/img-deer.png'; |   static const String imgDeer = 'assets/images/img-deer.png'; | ||||||
|   static const String imgLion = 'assets/images/img-lion.png'; |   static const String imgLion = 'assets/images/img-lion.png'; | ||||||
|   static const String imgGuideBank = 'assets/images/img-guide-bank.png'; |   static const String imgGuideBank = 'assets/images/img-guide-bank.png'; | ||||||
|   static const String imgGuide1 = 'assets/images/img-guide1.png'; |   static const String imgGuide1 = 'assets/images/img-guide1.png'; | ||||||
|   static const String imgGuide2 = 'assets/images/img-guide2.png'; |   static const String imgGuide2 = 'assets/images/img-guide2.png'; | ||||||
|   static const String imgOpenShopping = 'assets/images/img-open-shopping.png'; |   static const String imgOpenShopping = 'assets/images/img-open-shopping.png'; | ||||||
|   static const String imgPaymentSuccess = 'assets/images/img-payment-success.png'; |   static const String imgPaymentSuccess = | ||||||
|  |       'assets/images/img-payment-success.png'; | ||||||
|   static const String frameSignature = 'assets/images/frame-signature.png'; |   static const String frameSignature = 'assets/images/frame-signature.png'; | ||||||
|   static const String imgFinish = 'assets/images/img-finish.png'; |   static const String imgFinish = 'assets/images/img-finish.png'; | ||||||
|  |   static const String imgExpandPurchase = | ||||||
|  |       'assets/images/img-expand-purchase.png'; | ||||||
|  |   static const String imgEmptyTransaction = | ||||||
|  |       'assets/images/img-empty-transaction.png'; | ||||||
|  |   static const String bgProfile = 'assets/images/bg-profile.png'; | ||||||
|  |  | ||||||
|  |   static const Map<String, String> 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, | ||||||
|  |   }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,100 @@ | |||||||
|  | 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'; | ||||||
|  |  | ||||||
|  | class CardTransactionView extends StatelessWidget { | ||||||
|  |   final VoidCallback onTap; | ||||||
|  |   final String iconPath, type, amount, subs, step; | ||||||
|  |   final String? timeTransaction; | ||||||
|  |   const CardTransactionView({ | ||||||
|  |     Key? key, | ||||||
|  |     required this.step, | ||||||
|  |     required this.type, | ||||||
|  |     required this.amount, | ||||||
|  |     required this.iconPath, | ||||||
|  |     required this.subs, | ||||||
|  |     required this.onTap, | ||||||
|  |     this.timeTransaction, | ||||||
|  |   }) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     TextTheme textTheme = Theme.of(context).textTheme; | ||||||
|  |     return GestureDetector( | ||||||
|  |       onTap: onTap, | ||||||
|  |       child: Container( | ||||||
|  |         margin: const EdgeInsets.symmetric(vertical: 16.0), | ||||||
|  |         padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), | ||||||
|  |         decoration: BoxDecoration( | ||||||
|  |           color: Colors.white, | ||||||
|  |           border: Border.all(width: 1, color: ColorPalette.slate200), | ||||||
|  |           borderRadius: const BorderRadius.all(Radius.circular(12)), | ||||||
|  |         ), | ||||||
|  |         child: Row( | ||||||
|  |           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.center, | ||||||
|  |           children: [ | ||||||
|  |             SizedBox( | ||||||
|  |                 width: SizeConfig.width * .4, | ||||||
|  |                 child: Column( | ||||||
|  |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                   children: [ | ||||||
|  |                     Row( | ||||||
|  |                       children: [ | ||||||
|  |                         ImageView( | ||||||
|  |                             image: iconPath, width: SizeConfig.width * .12), | ||||||
|  |                         Padding( | ||||||
|  |                           padding: const EdgeInsets.only(left: 8.0), | ||||||
|  |                           child: Text( | ||||||
|  |                             type, | ||||||
|  |                             style: textTheme.headlineSmall, | ||||||
|  |                           ), | ||||||
|  |                         ), | ||||||
|  |                       ], | ||||||
|  |                     ), | ||||||
|  |                     Padding( | ||||||
|  |                       padding: const EdgeInsets.only(top: 16.0), | ||||||
|  |                       child: Text( | ||||||
|  |                         amount, | ||||||
|  |                         style: textTheme.headlineSmall, | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                   ], | ||||||
|  |                 )), | ||||||
|  |             SizedBox( | ||||||
|  |                 width: SizeConfig.width * .4, | ||||||
|  |                 child: Column( | ||||||
|  |                   crossAxisAlignment: CrossAxisAlignment.end, | ||||||
|  |                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|  |                   children: [ | ||||||
|  |                     SizedBox( | ||||||
|  |                         height: SizeConfig.height * .08, | ||||||
|  |                         child: Text( | ||||||
|  |                           subs, | ||||||
|  |                           style: const TextStyle(color: ColorPalette.primary), | ||||||
|  |                         )), | ||||||
|  |                     Row( | ||||||
|  |                       mainAxisAlignment: MainAxisAlignment.end, | ||||||
|  |                       children: [ | ||||||
|  |                         step == 'waiting' | ||||||
|  |                             ? const Icon(Icons.access_time_sharp, | ||||||
|  |                                 color: ColorPalette.slate400) | ||||||
|  |                             : const SizedBox(), | ||||||
|  |                         step == 'waiting' | ||||||
|  |                             ? Text(timeTransaction.toString()) | ||||||
|  |                             : const SizedBox(), | ||||||
|  |                         const Padding( | ||||||
|  |                           padding: EdgeInsets.only(left: 16.0), | ||||||
|  |                           child: Icon(Icons.arrow_forward_ios), | ||||||
|  |                         ), | ||||||
|  |                       ], | ||||||
|  |                     ), | ||||||
|  |                   ], | ||||||
|  |                 )), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,44 @@ | |||||||
|  | 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/core/utils/size_config.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class EmptyCardTransaction extends StatelessWidget { | ||||||
|  |   final VoidCallback onPressedButton; | ||||||
|  |   const EmptyCardTransaction({Key? key, required this.onPressedButton}) | ||||||
|  |       : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     TextTheme textTheme = Theme.of(context).textTheme; | ||||||
|  |     return Container( | ||||||
|  |       padding: const EdgeInsets.symmetric(vertical: 8.0), | ||||||
|  |       child: Center( | ||||||
|  |         child: Column( | ||||||
|  |           mainAxisAlignment: MainAxisAlignment.spaceAround, | ||||||
|  |           children: [ | ||||||
|  |             ImageView( | ||||||
|  |               image: PathAssets.imgEmptyTransaction, | ||||||
|  |               width: SizeConfig.width * .4, | ||||||
|  |             ), | ||||||
|  |             Text( | ||||||
|  |               'No Transaction Yet', | ||||||
|  |               style: textTheme.headlineSmall, | ||||||
|  |             ), | ||||||
|  |             Text( | ||||||
|  |               "Let's keep building your investment for even greater financial growth!", | ||||||
|  |               style: textTheme.bodyMedium, | ||||||
|  |               textAlign: TextAlign.center, | ||||||
|  |             ), | ||||||
|  |             ButtonView( | ||||||
|  |               name: 'Investing Now', | ||||||
|  |               width: SizeConfig.width * .5, | ||||||
|  |               onPressed: onPressedButton, | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -11,9 +11,9 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { | |||||||
|   const CustomAppBar({ |   const CustomAppBar({ | ||||||
|     Key? key, |     Key? key, | ||||||
|     required this.height, |     required this.height, | ||||||
|     this.leading, |  | ||||||
|     required this.title, |     required this.title, | ||||||
|     this.trailing, |     this.trailing, | ||||||
|  |     this.leading, | ||||||
|   }) : super(key: key); |   }) : super(key: key); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   | |||||||
| @@ -0,0 +1,119 @@ | |||||||
|  | import 'package:cims_apps/application/component/expandable_widget/see_more_less_widget.dart'; | ||||||
|  | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class ExpandableWidget extends StatelessWidget { | ||||||
|  |   final String? content; | ||||||
|  |   final double? fontSize; | ||||||
|  |   final int maxLinesToShow; | ||||||
|  |   final Alignment? alignmentMore; | ||||||
|  |   final bool? hideTextMore; | ||||||
|  |   final bool? hideIconMore; | ||||||
|  |  | ||||||
|  |   ExpandableWidget({ | ||||||
|  |     super.key, | ||||||
|  |     required this.content, | ||||||
|  |     this.fontSize, | ||||||
|  |     this.maxLinesToShow = 1, | ||||||
|  |     this.alignmentMore, | ||||||
|  |     this.hideTextMore = false, | ||||||
|  |     this.hideIconMore = true, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   ValueNotifier<bool> expanded = ValueNotifier(false); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final TextSpan textSpan = TextSpan( | ||||||
|  |       text: content ?? "", | ||||||
|  |       style: TextStyle( | ||||||
|  |         fontSize: fontSize ?? 16.0, | ||||||
|  |         color: ColorPalette.slate400, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     final TextPainter textPainter = TextPainter( | ||||||
|  |       text: textSpan, | ||||||
|  |       maxLines: expanded.value ? null : maxLinesToShow, | ||||||
|  |       textDirection: TextDirection.ltr, | ||||||
|  |       strutStyle: StrutStyle( | ||||||
|  |         fontSize: fontSize ?? 16.0, | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     textPainter.layout(maxWidth: SizeConfig.width); | ||||||
|  |  | ||||||
|  |     final int numberOfLines = textPainter.computeLineMetrics().length; | ||||||
|  |     return ValueListenableBuilder( | ||||||
|  |       valueListenable: expanded, | ||||||
|  |       builder: (context, values, _) { | ||||||
|  |         return Column( | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |           children: [ | ||||||
|  |             LayoutBuilder( | ||||||
|  |               builder: (BuildContext context, BoxConstraints constraints) { | ||||||
|  |                 if (!expanded.value && numberOfLines >= maxLinesToShow) { | ||||||
|  |                   return Column( | ||||||
|  |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                     children: [ | ||||||
|  |                       Text( | ||||||
|  |                         content ?? "", | ||||||
|  |                         maxLines: maxLinesToShow, | ||||||
|  |                         overflow: TextOverflow.ellipsis, | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           fontSize: fontSize ?? 16.0, | ||||||
|  |                           color: ColorPalette.slate400, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       /* See More :: type 1 - See More | 2 - See Less */ | ||||||
|  |                       SeeMoreLessWidget( | ||||||
|  |                         textData: 'See More', | ||||||
|  |                         type: 1, | ||||||
|  |                         section: 1, | ||||||
|  |                         onSeeMoreLessTap: () { | ||||||
|  |                           expanded.value = true; | ||||||
|  |                         }, | ||||||
|  |                         alignment: alignmentMore, | ||||||
|  |                         hideIconMore: hideIconMore!, | ||||||
|  |                         hideTextMore: hideTextMore!, | ||||||
|  |                       ), | ||||||
|  |                       /* See More :: type 1 - See More | 2 - See Less */ | ||||||
|  |                     ], | ||||||
|  |                   ); | ||||||
|  |                 } else { | ||||||
|  |                   return Column( | ||||||
|  |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                     children: [ | ||||||
|  |                       Text( | ||||||
|  |                         content ?? "", | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           fontSize: fontSize ?? 16.0, | ||||||
|  |                           color: ColorPalette.slate400, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       if (expanded.value && numberOfLines >= maxLinesToShow) | ||||||
|  |                       /* See Less :: type 1 - See More | 2 - See Less */ | ||||||
|  |                         SeeMoreLessWidget( | ||||||
|  |                           textData: 'See Less', | ||||||
|  |                           type: 2, | ||||||
|  |                           section: 1, | ||||||
|  |                           onSeeMoreLessTap: () { | ||||||
|  |                             expanded.value = false; | ||||||
|  |                           }, | ||||||
|  |                           alignment: alignmentMore, | ||||||
|  |                           hideIconMore: hideIconMore!, | ||||||
|  |                           hideTextMore: hideTextMore!, | ||||||
|  |                         ), | ||||||
|  |                       /* See Less :: type 1 - See More | 2 - See Less */ | ||||||
|  |                     ], | ||||||
|  |                   ); | ||||||
|  |                 } | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,74 @@ | |||||||
|  | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class SeeMoreLessWidget extends StatelessWidget { | ||||||
|  |   final String? textData; | ||||||
|  |   final int? type; /* type 1 - See More | 2 - See Less */ | ||||||
|  |   final Function? onSeeMoreLessTap; | ||||||
|  |   final int? | ||||||
|  |   section; /* 1: About the course | 2 - Who can take up this course? | 3 - Mentors | 4 - Course Video Reviews */ | ||||||
|  |   final Alignment? alignment; | ||||||
|  |   final bool hideTextMore; | ||||||
|  |   final bool hideIconMore; | ||||||
|  |  | ||||||
|  |   const SeeMoreLessWidget({ | ||||||
|  |     super.key, | ||||||
|  |     required this.textData, | ||||||
|  |     required this.type, | ||||||
|  |     required this.onSeeMoreLessTap, | ||||||
|  |     required this.section, | ||||||
|  |     required this.alignment, | ||||||
|  |     required this.hideTextMore, | ||||||
|  |     required this.hideIconMore, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Align( | ||||||
|  |       alignment: alignment ?? Alignment.centerLeft, | ||||||
|  |       child: InkWell( | ||||||
|  |         onTap: () { | ||||||
|  |           if (onSeeMoreLessTap != null) { | ||||||
|  |             onSeeMoreLessTap!(); | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         child: Text.rich( | ||||||
|  |           softWrap: true, | ||||||
|  |           style: const TextStyle( | ||||||
|  |             color: ColorPalette.primary, | ||||||
|  |           ), | ||||||
|  |           textAlign: TextAlign.start, | ||||||
|  |           TextSpan( | ||||||
|  |             text: "", | ||||||
|  |             children: [ | ||||||
|  |               if(!hideTextMore) | ||||||
|  |                 TextSpan( | ||||||
|  |                   text: textData, | ||||||
|  |                   style: const TextStyle( | ||||||
|  |                       color: ColorPalette.primary, | ||||||
|  |                       decoration: TextDecoration.underline, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               if(!hideTextMore && !hideIconMore) | ||||||
|  |                 const WidgetSpan( | ||||||
|  |                   child: SizedBox( | ||||||
|  |                     width: 3.0, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               if(!hideIconMore) | ||||||
|  |                 WidgetSpan( | ||||||
|  |                   child: Icon( | ||||||
|  |                     (type == 1) | ||||||
|  |                         ? Icons.keyboard_arrow_down | ||||||
|  |                         : Icons.keyboard_arrow_up, | ||||||
|  |                     color: ColorPalette.slate300, | ||||||
|  |                     size: 28, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -8,22 +8,26 @@ class ListTileView extends StatelessWidget { | |||||||
|   final String title; |   final String title; | ||||||
|   final VoidCallback? onPressed; |   final VoidCallback? onPressed; | ||||||
|   final Widget? prefixIcon, suffixIcon; |   final Widget? prefixIcon, suffixIcon; | ||||||
|   final Color? colorTitle; |   final EdgeInsetsGeometry? padding, margin; | ||||||
|  |   final TextStyle? textStyle; | ||||||
|   const ListTileView( |   const ListTileView( | ||||||
|       {Key? key, |       {Key? key, | ||||||
|       required this.title, |       required this.title, | ||||||
|       this.onPressed, |       this.onPressed, | ||||||
|       this.prefixIcon, |       this.prefixIcon, | ||||||
|       this.suffixIcon, |       this.suffixIcon, | ||||||
|       this.colorTitle}) |       this.padding, | ||||||
|  |       this.textStyle, | ||||||
|  |       this.margin}) | ||||||
|       : super(key: key); |       : super(key: key); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Container( |     return Container( | ||||||
|       width: SizeConfig.width, |       width: SizeConfig.width, | ||||||
|       padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), |       padding: padding ?? | ||||||
|       margin: const EdgeInsets.symmetric(vertical: 16.0), |           const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), | ||||||
|  |       margin: margin ?? const EdgeInsets.symmetric(vertical: 16.0), | ||||||
|       decoration: BoxDecoration( |       decoration: BoxDecoration( | ||||||
|         color: ColorPalette.blue50, |         color: ColorPalette.blue50, | ||||||
|         borderRadius: BorderRadius.circular(10), |         borderRadius: BorderRadius.circular(10), | ||||||
| @@ -47,22 +51,23 @@ class ListTileView extends StatelessWidget { | |||||||
|           Expanded( |           Expanded( | ||||||
|             child: Text( |             child: Text( | ||||||
|               title, |               title, | ||||||
|               style: TextStyle( |               style: textStyle ?? | ||||||
|                 fontWeight: FontWeight.w600, |                   const TextStyle( | ||||||
|                 color: colorTitle ?? ColorPalette.slate500, |                     fontWeight: FontWeight.w600, | ||||||
|               ), |                     color: ColorPalette.slate500, | ||||||
|  |                   ), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|           suffixIcon != null |           suffixIcon ?? | ||||||
|               ? IconButton( |               IconButton( | ||||||
|                   onPressed: onPressed, |                 onPressed: onPressed, | ||||||
|                   icon: const Icon( |                 icon: const Icon( | ||||||
|                     Icons.arrow_forward_ios, |                   Icons.arrow_forward_ios, | ||||||
|                     color: ColorPalette.primary, |                   color: ColorPalette.primary, | ||||||
|                     size: 20, |                   size: 20, | ||||||
|                   ), |                 ), | ||||||
|                 ) |               ), | ||||||
|               : const SizedBox(), |           // : const SizedBox(), | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -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/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/utils/size_config.dart'; | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| @@ -101,8 +103,9 @@ class NumericPad extends StatelessWidget { | |||||||
|               number, |               number, | ||||||
|               textAlign: TextAlign.center, |               textAlign: TextAlign.center, | ||||||
|               style: TextStyle( |               style: TextStyle( | ||||||
|                   fontSize: 28, |                 fontSize: 28, | ||||||
|                   fontWeight: FontWeight.bold |                 fontWeight: FontWeight.bold, | ||||||
|  |                 color: ColorPalette.slate800 | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
| @@ -117,8 +120,9 @@ class NumericPad extends StatelessWidget { | |||||||
|             onNumberSelected(''); |             onNumberSelected(''); | ||||||
|           }, |           }, | ||||||
|           child: Icon( |           child: Icon( | ||||||
|             Icons.highlight_remove, |             Icons.backspace_outlined, | ||||||
|             size: 28, |             size: 28, | ||||||
|  |             color: ColorPalette.slate800, | ||||||
|           ), |           ), | ||||||
|         ) |         ) | ||||||
|     ); |     ); | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								lib/application/component/radio_agreement.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,57 @@ | |||||||
|  | import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart'; | ||||||
|  | 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: ExpandableWidget( | ||||||
|  |               content: desc, | ||||||
|  |               maxLinesToShow: 3, | ||||||
|  |             ) | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/utils/size_config.dart'; | import 'package:cims_apps/core/utils/size_config.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/risk_profile/risk_profile_view_model/risk_profile_view_model.dart'; | ||||||
| @@ -73,20 +74,20 @@ class RiskProfile extends StatelessWidget { | |||||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, |               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|               children: [ |               children: [ | ||||||
|                 Container( |                 Container( | ||||||
|                   padding: EdgeInsets.all(24), |                   padding: const EdgeInsets.all(24), | ||||||
|                   child: Column( |                   child: Column( | ||||||
|                     crossAxisAlignment: CrossAxisAlignment.start, |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                     children: [ |                     children: [ | ||||||
|                       Text( |                       Text( | ||||||
|                         riskProfile.type, |                         riskProfile.type, | ||||||
|                         style: TextStyle( |                         style: const TextStyle( | ||||||
|                             fontWeight: FontWeight.bold, |                             fontWeight: FontWeight.bold, | ||||||
|                             fontSize: 24, |                             fontSize: 24, | ||||||
|                             color: ColorPalette.white |                             color: ColorPalette.white | ||||||
|                         ), |                         ), | ||||||
|                       ), |                       ), | ||||||
|                       SizedBox(height: 16,), |                       const SizedBox(height: 16,), | ||||||
|                       Text('Total Score :', |                       const Text('Total Score :', | ||||||
|                         style: TextStyle( |                         style: TextStyle( | ||||||
|                             fontWeight: FontWeight.bold, |                             fontWeight: FontWeight.bold, | ||||||
|                             fontSize: 16, |                             fontSize: 16, | ||||||
| @@ -94,7 +95,7 @@ class RiskProfile extends StatelessWidget { | |||||||
|                         ), |                         ), | ||||||
|                       ), |                       ), | ||||||
|                       Text('$totalScore', |                       Text('$totalScore', | ||||||
|                         style: TextStyle( |                         style: const TextStyle( | ||||||
|                             fontWeight: FontWeight.bold, |                             fontWeight: FontWeight.bold, | ||||||
|                             fontSize: 28, |                             fontSize: 28, | ||||||
|                             color: ColorPalette.white |                             color: ColorPalette.white | ||||||
| @@ -107,20 +108,20 @@ class RiskProfile extends StatelessWidget { | |||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         SizedBox( |         const SizedBox( | ||||||
|           height: 24, |           height: 24, | ||||||
|         ), |         ), | ||||||
|         Text( |         ExpandableWidget( | ||||||
|             riskProfile.desc, |           content: riskProfile.desc, | ||||||
|             style: TextStyle( |           hideTextMore: true, | ||||||
|                 color: ColorPalette.slate500, |           hideIconMore: false, | ||||||
|                 fontSize: 16 |           maxLinesToShow: 4, | ||||||
|             ) |           alignmentMore: Alignment.center, | ||||||
|         ), |         ), | ||||||
|         SizedBox( |         const SizedBox( | ||||||
|           height: 24, |           height: 24, | ||||||
|         ), |         ), | ||||||
|         Text( |         const Text( | ||||||
|           'Suitable Product', |           'Suitable Product', | ||||||
|           style: TextStyle( |           style: TextStyle( | ||||||
|               color: ColorPalette.slate800, |               color: ColorPalette.slate800, | ||||||
| @@ -128,7 +129,7 @@ class RiskProfile extends StatelessWidget { | |||||||
|               fontSize: 18 |               fontSize: 18 | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         SizedBox( |         const SizedBox( | ||||||
|           height: 16, |           height: 16, | ||||||
|         ), |         ), | ||||||
|         rowSuitableProduct ? |         rowSuitableProduct ? | ||||||
| @@ -137,7 +138,7 @@ class RiskProfile extends StatelessWidget { | |||||||
|               return Expanded( |               return Expanded( | ||||||
|                 child: Container( |                 child: Container( | ||||||
|                   margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0), |                   margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0), | ||||||
|                   padding: EdgeInsets.all(16), |                   padding: const EdgeInsets.all(16), | ||||||
|                   decoration: BoxDecoration( |                   decoration: BoxDecoration( | ||||||
|                     border: Border.all(color: ColorPalette.slate200), |                     border: Border.all(color: ColorPalette.slate200), | ||||||
|                     borderRadius: BorderRadius.circular(6) |                     borderRadius: BorderRadius.circular(6) | ||||||
| @@ -146,18 +147,18 @@ class RiskProfile extends StatelessWidget { | |||||||
|                     crossAxisAlignment: CrossAxisAlignment.start, |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                     children: [ |                     children: [ | ||||||
|                       Container( |                       Container( | ||||||
|                           padding: EdgeInsets.all(8), |                           padding: const EdgeInsets.all(8), | ||||||
|                           decoration: BoxDecoration( |                           decoration: BoxDecoration( | ||||||
|                               shape: BoxShape.circle, |                               shape: BoxShape.circle, | ||||||
|                               color: riskProfile.color.withOpacity(0.1) |                               color: riskProfile.color.withOpacity(0.1) | ||||||
|                           ), |                           ), | ||||||
|                           child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color) |                           child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color) | ||||||
|                       ), |                       ), | ||||||
|                       SizedBox( |                       const SizedBox( | ||||||
|                         height: 12, |                         height: 12, | ||||||
|                       ), |                       ), | ||||||
|                       Text(e.value['desc'], |                       Text(e.value['desc'], | ||||||
|                         style: TextStyle( |                         style: const TextStyle( | ||||||
|                             fontSize: 16, |                             fontSize: 16, | ||||||
|                             fontWeight: FontWeight.bold, |                             fontWeight: FontWeight.bold, | ||||||
|                             color: ColorPalette.slate800 |                             color: ColorPalette.slate800 | ||||||
| @@ -173,7 +174,7 @@ class RiskProfile extends StatelessWidget { | |||||||
|           runSpacing: 16, |           runSpacing: 16, | ||||||
|           children: riskProfile.suitableProduct.map((e) { |           children: riskProfile.suitableProduct.map((e) { | ||||||
|             return Container( |             return Container( | ||||||
|               padding: EdgeInsets.all(16), |               padding: const EdgeInsets.all(16), | ||||||
|               decoration: BoxDecoration( |               decoration: BoxDecoration( | ||||||
|                 borderRadius: BorderRadius.circular(6), |                 borderRadius: BorderRadius.circular(6), | ||||||
|                 border: Border.all(color: ColorPalette.slate200), |                 border: Border.all(color: ColorPalette.slate200), | ||||||
| @@ -181,7 +182,7 @@ class RiskProfile extends StatelessWidget { | |||||||
|               child: Row( |               child: Row( | ||||||
|                 children: [ |                 children: [ | ||||||
|                   Container( |                   Container( | ||||||
|                       padding: EdgeInsets.all(8), |                       padding: const EdgeInsets.all(8), | ||||||
|                       alignment: Alignment.center, |                       alignment: Alignment.center, | ||||||
|                       decoration: BoxDecoration( |                       decoration: BoxDecoration( | ||||||
|                           shape: BoxShape.circle, |                           shape: BoxShape.circle, | ||||||
| @@ -189,12 +190,12 @@ class RiskProfile extends StatelessWidget { | |||||||
|                       ), |                       ), | ||||||
|                       child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color) |                       child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color) | ||||||
|                   ), |                   ), | ||||||
|                   SizedBox( |                   const SizedBox( | ||||||
|                     width: 12, |                     width: 12, | ||||||
|                   ), |                   ), | ||||||
|                   Expanded( |                   Expanded( | ||||||
|                     child: Text(e['desc'], |                     child: Text(e['desc'], | ||||||
|                       style: TextStyle( |                       style: const TextStyle( | ||||||
|                           fontSize: 18, |                           fontSize: 18, | ||||||
|                           fontWeight: FontWeight.bold, |                           fontWeight: FontWeight.bold, | ||||||
|                           color: ColorPalette.slate800 |                           color: ColorPalette.slate800 | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ class SelectFormView extends StatelessWidget { | |||||||
|     bottomSheet() { |     bottomSheet() { | ||||||
|       showModalBottomSheet<void>( |       showModalBottomSheet<void>( | ||||||
|         context: context, |         context: context, | ||||||
|  |         isDismissible: false, | ||||||
|         shape: RoundedRectangleBorder( |         shape: RoundedRectangleBorder( | ||||||
|           borderRadius: BorderRadius.only( |           borderRadius: BorderRadius.only( | ||||||
|             topLeft: _borderRadius, |             topLeft: _borderRadius, | ||||||
| @@ -82,7 +83,10 @@ class SelectFormView extends StatelessWidget { | |||||||
|                         ), |                         ), | ||||||
|                       ), |                       ), | ||||||
|                       IconButton( |                       IconButton( | ||||||
|                           onPressed: () => Navigator.pop(context), |                           onPressed: () { | ||||||
|  |                             ctrl?.clear(); | ||||||
|  |                             Navigator.pop(context); | ||||||
|  |                           }, | ||||||
|                           icon: const Icon( |                           icon: const Icon( | ||||||
|                             Icons.clear, |                             Icons.clear, | ||||||
|                             size: 26, |                             size: 26, | ||||||
| @@ -134,7 +138,7 @@ class SelectFormView extends StatelessWidget { | |||||||
|                                 onTap: () { |                                 onTap: () { | ||||||
|                                   stateSetter(() { |                                   stateSetter(() { | ||||||
|                                     ctrl?.text = e.text; |                                     ctrl?.text = e.text; | ||||||
|                                     onSelect(e.key); |                                     onSelect(e.text); | ||||||
|                                   }); |                                   }); | ||||||
|                                 }, |                                 }, | ||||||
|                               ), |                               ), | ||||||
| @@ -148,7 +152,9 @@ class SelectFormView extends StatelessWidget { | |||||||
|                     name: 'Select', |                     name: 'Select', | ||||||
|                     marginVertical: 4.0, |                     marginVertical: 4.0, | ||||||
|                     onPressed: () { |                     onPressed: () { | ||||||
|                       Navigator.pop(context); |                       if (ctrl!.text.isNotEmpty) { | ||||||
|  |                         Navigator.pop(context); | ||||||
|  |                       } | ||||||
|                     }, |                     }, | ||||||
|                   ) |                   ) | ||||||
|                 ], |                 ], | ||||||
|   | |||||||
| @@ -36,8 +36,8 @@ class GoalInvestingView extends StatelessWidget { | |||||||
|                   routePush( |                   routePush( | ||||||
|                     context, |                     context, | ||||||
|                     page: OtherPlanView( |                     page: OtherPlanView( | ||||||
|                       selectedPlan: (value) { |                       selectedPlan: (val) { | ||||||
|                         onListSelected(e.value.title); |                         onListSelected(val); | ||||||
|                       }, |                       }, | ||||||
|                     ) |                     ) | ||||||
|                   ); |                   ); | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | import 'dart:math'; | ||||||
|  |  | ||||||
| import 'package:cims_apps/application/component/button/button_view.dart'; | import 'package:cims_apps/application/component/button/button_view.dart'; | ||||||
| import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; | import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| @@ -6,9 +8,13 @@ import 'package:cims_apps/core/utils/size_config.dart'; | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| class InputInvestmentView extends StatefulWidget { | class InputInvestmentView extends StatefulWidget { | ||||||
|   final String selectedPlan; |   final String? currentPlan; | ||||||
|  |   final void Function()? changePlan; | ||||||
|  |   final int? currentPrice; | ||||||
|  |   final int? minimumPrice; | ||||||
|  |   final int? maximumPrice; | ||||||
|   final void Function(String value) nextMove; |   final void Function(String value) nextMove; | ||||||
|   const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove}); |   const InputInvestmentView({super.key, required this.nextMove, this.currentPlan, this.minimumPrice, this.maximumPrice, this.currentPrice, this.changePlan}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   State<InputInvestmentView> createState() => _InputInvestmentViewState(); |   State<InputInvestmentView> createState() => _InputInvestmentViewState(); | ||||||
| @@ -17,10 +23,35 @@ class InputInvestmentView extends StatefulWidget { | |||||||
| class _InputInvestmentViewState extends State<InputInvestmentView> { | class _InputInvestmentViewState extends State<InputInvestmentView> { | ||||||
|   TextEditingController inputController = TextEditingController(); |   TextEditingController inputController = TextEditingController(); | ||||||
|  |  | ||||||
|  |   void validationInputValue(String currentValue) { | ||||||
|  |     currentValue = currentValue.replaceAll('Rp ', '').replaceAll('.', ''); | ||||||
|  |     if(currentValue.isEmpty){ | ||||||
|  |       currentValue = '0'; | ||||||
|  |     } | ||||||
|  |     double parseValue = double.parse(currentValue); | ||||||
|  |     if(widget.minimumPrice != null){ | ||||||
|  |       if(parseValue <= widget.minimumPrice!){ | ||||||
|  |         parseValue = widget.minimumPrice!.toDouble(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if(widget.maximumPrice != null){ | ||||||
|  |       if(parseValue >= widget.maximumPrice!){ | ||||||
|  |         parseValue = widget.maximumPrice!.toDouble(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     // TODO: implement initState |     // TODO: implement initState | ||||||
|     inputController.text = 'Rp 0'; |     if(widget.currentPrice != null){ | ||||||
|  |       inputController.text = NumberFormatter.numberCurrency(widget.currentPrice, 'Rp ', 'id_ID', decimalDigits: 0); | ||||||
|  |     }else{ | ||||||
|  |       inputController.text = 'Rp 0'; | ||||||
|  |     } | ||||||
|     super.initState(); |     super.initState(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -41,56 +72,53 @@ class _InputInvestmentViewState extends State<InputInvestmentView> { | |||||||
|       child: Column( |       child: Column( | ||||||
|         mainAxisSize: MainAxisSize.min, |         mainAxisSize: MainAxisSize.min, | ||||||
|         children: [ |         children: [ | ||||||
|           SizedBox(height: 16), |  | ||||||
|           Padding( |           Padding( | ||||||
|             padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), |             padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), | ||||||
|             child: Column( |             child: Column( | ||||||
|               crossAxisAlignment: CrossAxisAlignment.start, |               crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|               children: [ |               children: [ | ||||||
|                 Row( |                 if(widget.currentPlan != null) | ||||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, |                   Row( | ||||||
|                   children: [ |                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                     Text(widget.selectedPlan, |                     children: [ | ||||||
|                       style: TextStyle( |                       Text(widget.currentPlan ?? '', | ||||||
|                         fontSize: 20, |                         style: const TextStyle( | ||||||
|                         fontWeight: FontWeight.w700, |                           fontSize: 20, | ||||||
|  |                           fontWeight: FontWeight.w700, | ||||||
|  |                         ), | ||||||
|                       ), |                       ), | ||||||
|                     ), |                       InkWell( | ||||||
|                     Row( |                         borderRadius: BorderRadius.circular(16), | ||||||
|                       children: [ |                         onTap: widget.changePlan, | ||||||
|                         Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20), |                         child: const Row( | ||||||
|                         SizedBox(width: 4), |                           children: [ | ||||||
|                         Text('Change', |                             Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20), | ||||||
|                           style: TextStyle( |                             SizedBox(width: 4), | ||||||
|                               fontSize: 16, |                             Text('Change', | ||||||
|                               fontWeight: FontWeight.w600, |                               style: TextStyle( | ||||||
|                               color: ColorPalette.primary |                                   fontSize: 16, | ||||||
|                           ), |                                   fontWeight: FontWeight.w600, | ||||||
|                         ) |                                   color: ColorPalette.primary | ||||||
|                       ], |                               ), | ||||||
|                     ) |                             ) | ||||||
|                   ], |                           ], | ||||||
|                 ), |                         ), | ||||||
|  |                       ) | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|                 TextField( |                 TextField( | ||||||
|                   controller: inputController, |                   controller: inputController, | ||||||
|                   textAlign: TextAlign.center, |                   textAlign: TextAlign.center, | ||||||
|                   style: TextStyle( |                   style: const TextStyle( | ||||||
|                       fontSize: 28, |                       fontSize: 28, | ||||||
|                       fontWeight: FontWeight.w600, |                       fontWeight: FontWeight.w600, | ||||||
|                       color: ColorPalette.slate800 |                       color: ColorPalette.slate800 | ||||||
|                   ), |                   ), | ||||||
|                   keyboardType: TextInputType.number, |                   keyboardType: TextInputType.number, | ||||||
|                   onChanged: (value) { |                   onChanged: (value) { | ||||||
|                     value = value.replaceAll('Rp ', '').replaceAll('.', ''); |                     validationInputValue(value); | ||||||
|                     double parseValue = double.parse(value); |  | ||||||
|                     if(value.isNotEmpty){ |  | ||||||
|                       inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0); |  | ||||||
|                     }else{ |  | ||||||
|                       inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0); |  | ||||||
|                     } |  | ||||||
|                   }, |                   }, | ||||||
|                   decoration: InputDecoration( |                   decoration: const InputDecoration( | ||||||
|                       enabledBorder: UnderlineInputBorder( |                       enabledBorder: UnderlineInputBorder( | ||||||
|                         borderSide: BorderSide( |                         borderSide: BorderSide( | ||||||
|                             color: ColorPalette.primary, |                             color: ColorPalette.primary, | ||||||
| @@ -99,30 +127,36 @@ class _InputInvestmentViewState extends State<InputInvestmentView> { | |||||||
|                       ) |                       ) | ||||||
|                   ), |                   ), | ||||||
|                 ), |                 ), | ||||||
|                 SizedBox(height: 12), |                 const SizedBox(height: 12), | ||||||
|                 Text('Minimum Budget Rp1,000,000', |                 if(widget.minimumPrice != null) | ||||||
|                   style: TextStyle( |                   Text('Minimum ${NumberFormatter.numberCurrency(widget.minimumPrice, 'Rp ', 'id_ID')}', | ||||||
|                       color: ColorPalette.slate400, |                     style: const TextStyle( | ||||||
|                       fontSize: 16, |                         color: ColorPalette.slate400, | ||||||
|                       fontWeight: FontWeight.w600 |                         fontSize: 16, | ||||||
|  |                         fontWeight: FontWeight.w600 | ||||||
|  |                     ), | ||||||
|                   ), |                   ), | ||||||
|                 ), |                 if(widget.maximumPrice != null) | ||||||
|                 SizedBox(height: 16), |                   Text('Maximum ${NumberFormatter.numberCurrency(widget.maximumPrice, 'Rp ', 'id_ID')}', | ||||||
|  |                     style: const TextStyle( | ||||||
|  |                         color: ColorPalette.slate400, | ||||||
|  |                         fontSize: 16, | ||||||
|  |                         fontWeight: FontWeight.w600 | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 const SizedBox(height: 16), | ||||||
|                 NumericPad(onNumberSelected: (p0) { |                 NumericPad(onNumberSelected: (p0) { | ||||||
|                   String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', ''); |                   String currentValue = inputController.text; | ||||||
|                   String getNumeric = p0; |  | ||||||
|                   if(p0.isNotEmpty){ |                   if(p0.isNotEmpty){ | ||||||
|                     if(checkIsZeroInput != '0'){ |                     if(currentValue != '0'){ | ||||||
|                       getNumeric = checkIsZeroInput + getNumeric; |                       currentValue = currentValue + p0; | ||||||
|                     } |                     } | ||||||
|                   }else{ |                   }else{ | ||||||
|                     getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1); |                     currentValue = currentValue.substring(0, currentValue.length - 1); | ||||||
|                   } |                   } | ||||||
|                   String formatNumeric = NumberFormatter.numberCurrency( |                   validationInputValue(currentValue); | ||||||
|                       double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ','); |  | ||||||
|                   inputController.text = formatNumeric; |  | ||||||
|                 }), |                 }), | ||||||
|                 SizedBox(height: 8), |                 const SizedBox(height: 24), | ||||||
|                 ButtonView( |                 ButtonView( | ||||||
|                   name: 'Next', |                   name: 'Next', | ||||||
|                   onPressed: () { |                   onPressed: () { | ||||||
| @@ -130,7 +164,7 @@ class _InputInvestmentViewState extends State<InputInvestmentView> { | |||||||
|                   }, |                   }, | ||||||
|                   width: SizeConfig.width, |                   width: SizeConfig.width, | ||||||
|                   heightWrapContent: true, |                   heightWrapContent: true, | ||||||
|                   contentPadding: EdgeInsets.symmetric(vertical: 16), |                   contentPadding: const EdgeInsets.symmetric(vertical: 16), | ||||||
|                   marginVertical: 0, |                   marginVertical: 0, | ||||||
|                 ) |                 ) | ||||||
|               ], |               ], | ||||||
| @@ -138,6 +172,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> { | |||||||
|           ), |           ), | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
|     );; |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | import 'dart:math'; | ||||||
|  |  | ||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | 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/button/button_view.dart'; | ||||||
| import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | ||||||
| @@ -72,6 +74,8 @@ class _OtherPlanViewState extends State<OtherPlanView> { | |||||||
|           disabled: !(selectedPlan.img != ''), |           disabled: !(selectedPlan.img != ''), | ||||||
|           onPressed: () { |           onPressed: () { | ||||||
|             Navigator.pop(context); |             Navigator.pop(context); | ||||||
|  |             print('haloo'); | ||||||
|  |             print(selectedPlan.name); | ||||||
|             widget.selectedPlan(selectedPlan.name); |             widget.selectedPlan(selectedPlan.name); | ||||||
|           }, |           }, | ||||||
|           heightWrapContent: true, |           heightWrapContent: true, | ||||||
| @@ -91,6 +95,7 @@ class _OtherPlanViewState extends State<OtherPlanView> { | |||||||
|         if(plan.name == 'Create Plan'){ |         if(plan.name == 'Create Plan'){ | ||||||
|           showModalBottomSheet( |           showModalBottomSheet( | ||||||
|             context: context, |             context: context, | ||||||
|  |             isDismissible: false, | ||||||
|             builder: (context) => modalCreatePlan(), |             builder: (context) => modalCreatePlan(), | ||||||
|           ); |           ); | ||||||
|         } |         } | ||||||
| @@ -150,6 +155,9 @@ class _OtherPlanViewState extends State<OtherPlanView> { | |||||||
|               GestureDetector( |               GestureDetector( | ||||||
|                 onTap: () { |                 onTap: () { | ||||||
|                   Navigator.pop(context); |                   Navigator.pop(context); | ||||||
|  |                   setState(() { | ||||||
|  |                     selectedPlan = Plan('', ''); | ||||||
|  |                   }); | ||||||
|                 }, |                 }, | ||||||
|                 child: Icon(Icons.close_rounded), |                 child: Icon(Icons.close_rounded), | ||||||
|               ) |               ) | ||||||
| @@ -161,12 +169,12 @@ class _OtherPlanViewState extends State<OtherPlanView> { | |||||||
|           ), |           ), | ||||||
|           SizedBox(height: 24), |           SizedBox(height: 24), | ||||||
|           ButtonView( |           ButtonView( | ||||||
|             name: 'Select', |             name: 'Next', | ||||||
|             marginVertical: 0, |             marginVertical: 0, | ||||||
|             disabled: !(createController.text != ''), |             disabled: !(createController.text != ''), | ||||||
|             onPressed: () { |             onPressed: () { | ||||||
|               Navigator.of(context)..pop()..pop(); |               Navigator.of(context)..pop()..pop(); | ||||||
|               widget.selectedPlan(selectedPlan.name); |               widget.selectedPlan(createController.text); | ||||||
|             }, |             }, | ||||||
|             heightWrapContent: true, |             heightWrapContent: true, | ||||||
|             width: SizeConfig.width, |             width: SizeConfig.width, | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import 'package:cims_apps/application/component/button/button_view.dart'; | 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/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| import 'package:cims_apps/core/utils/number_formatter.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:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| class TotalPaymentView extends StatefulWidget { | class TotalPaymentView extends StatelessWidget { | ||||||
|   final int totalInvest; |   final int totalInvest; | ||||||
|   final List<Product> listProduct; |   final List<Product> listProduct; | ||||||
|  |   final bool isAgree; | ||||||
|  |   final void Function() onTapAgree; | ||||||
|   const TotalPaymentView({ |   const TotalPaymentView({ | ||||||
|     super.key, |     super.key, | ||||||
|     required this.listProduct, |     required this.listProduct, | ||||||
|     required this.totalInvest, |     required this.totalInvest, | ||||||
|  |     required this.isAgree, | ||||||
|  |     required this.onTapAgree, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   @override |  | ||||||
|   State<TotalPaymentView> createState() => _TotalPaymentViewState(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| class _TotalPaymentViewState extends State<TotalPaymentView> { |  | ||||||
|   bool isAgreement = false; |  | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return SingleChildScrollView( |     return SingleChildScrollView( | ||||||
| @@ -49,7 +47,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|             ...widget.listProduct.asMap().entries.map((e) { |             ...listProduct.asMap().entries.map((e) { | ||||||
|               return Container( |               return Container( | ||||||
|                 padding: const EdgeInsets.only( |                 padding: const EdgeInsets.only( | ||||||
|                     left: 16, right: 24, bottom: 16, top: 16), |                     left: 16, right: 24, bottom: 16, top: 16), | ||||||
| @@ -75,7 +73,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|                         flex: 7, |                         flex: 7, | ||||||
|                         child: Text( |                         child: Text( | ||||||
|                           NumberFormatter.numberCurrency( |                           NumberFormatter.numberCurrency( | ||||||
|                               widget.totalInvest * e.value.totalPercent!, |                               totalInvest * e.value.totalPercent!, | ||||||
|                               'Rp ', |                               'Rp ', | ||||||
|                               'id_ID'), |                               'id_ID'), | ||||||
|                           textAlign: TextAlign.end, |                           textAlign: TextAlign.end, | ||||||
| @@ -129,7 +127,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|                   ), |                   ), | ||||||
|                   Text( |                   Text( | ||||||
|                     NumberFormatter.numberCurrency( |                     NumberFormatter.numberCurrency( | ||||||
|                         widget.totalInvest, 'Rp ', 'id_ID'), |                         totalInvest, 'Rp ', 'id_ID'), | ||||||
|                     textAlign: TextAlign.end, |                     textAlign: TextAlign.end, | ||||||
|                     style: const TextStyle( |                     style: const TextStyle( | ||||||
|                         fontWeight: FontWeight.w700, |                         fontWeight: FontWeight.w700, | ||||||
| @@ -139,7 +137,13 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|             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.', | ||||||
|  |               onTap: () { | ||||||
|  |                 onTapAgree(); | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|             Container( |             Container( | ||||||
|               padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), |               padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), | ||||||
|               child: Row( |               child: Row( | ||||||
| @@ -154,7 +158,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|                   ), |                   ), | ||||||
|                   Text( |                   Text( | ||||||
|                     NumberFormatter.numberCurrency( |                     NumberFormatter.numberCurrency( | ||||||
|                         widget.totalInvest, 'Rp ', 'id_ID'), |                         totalInvest, 'Rp ', 'id_ID'), | ||||||
|                     textAlign: TextAlign.end, |                     textAlign: TextAlign.end, | ||||||
|                     style: const TextStyle( |                     style: const TextStyle( | ||||||
|                         fontWeight: FontWeight.w700, |                         fontWeight: FontWeight.w700, | ||||||
| @@ -165,16 +169,16 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|             ButtonView( |             ButtonView( | ||||||
|               disabled: !isAgreement, |               disabled: !isAgree, | ||||||
|               name: 'Subscribe Now', |               name: 'Subscribe Now', | ||||||
|               onPressed: () { |               onPressed: () { | ||||||
|                 routePush(context, |                 routePush(context, | ||||||
|                     page: PaymentMethodView( |                     page: PaymentMethodView( | ||||||
|                       totalInvest: widget.totalInvest, |                       totalInvest: totalInvest, | ||||||
|                     )); |                     )); | ||||||
|               }, |               }, | ||||||
|               disabledBgColor: ColorPalette.slate200.withOpacity(0.5), |               disabledBgColor: ColorPalette.slate200.withOpacity(0.5), | ||||||
|               textColor: isAgreement ? Colors.white : ColorPalette.slate400, |               textColor: isAgree ? Colors.white : ColorPalette.slate400, | ||||||
|               textWeight: FontWeight.w700, |               textWeight: FontWeight.w700, | ||||||
|               textSize: 20, |               textSize: 20, | ||||||
|               backgroundColor: ColorPalette.primary, |               backgroundColor: ColorPalette.primary, | ||||||
| @@ -185,71 +189,67 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Widget buttonAgreement() { |   // Widget buttonAgreement() { | ||||||
|     bool isAgree = isAgreement; |   //   return Padding( | ||||||
|     return Padding( |   //     padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), | ||||||
|       padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), |   //     child: Row( | ||||||
|       child: Row( |   //       crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|         crossAxisAlignment: CrossAxisAlignment.start, |   //       children: [ | ||||||
|         children: [ |   //         GestureDetector( | ||||||
|           GestureDetector( |   //           onTap: () { | ||||||
|             onTap: () { |   //           }, | ||||||
|               setState(() { |   //           child: AnimatedContainer( | ||||||
|                 isAgreement = !isAgreement; |   //             margin: const EdgeInsets.only(top: 4), | ||||||
|               }); |   //             duration: const Duration(milliseconds: 200), | ||||||
|             }, |   //             height: 16, | ||||||
|             child: AnimatedContainer( |   //             width: 16, | ||||||
|               margin: const EdgeInsets.only(top: 4), |   //             padding: const EdgeInsets.all(1), | ||||||
|               duration: const Duration(milliseconds: 200), |   //             alignment: Alignment.center, | ||||||
|               height: 16, |   //             decoration: BoxDecoration( | ||||||
|               width: 16, |   //                 shape: BoxShape.circle, | ||||||
|               padding: const EdgeInsets.all(1), |   //                 border: Border.all( | ||||||
|               alignment: Alignment.center, |   //                     color: isAgree | ||||||
|               decoration: BoxDecoration( |   //                         ? ColorPalette.primary | ||||||
|                   shape: BoxShape.circle, |   //                         : ColorPalette.slate200)), | ||||||
|                   border: Border.all( |   //             child: AnimatedContainer( | ||||||
|                       color: isAgree |   //               duration: const Duration(milliseconds: 200), | ||||||
|                           ? ColorPalette.primary |   //               child: Container( | ||||||
|                           : ColorPalette.slate200)), |   //                 decoration: BoxDecoration( | ||||||
|               child: AnimatedContainer( |   //                     color: | ||||||
|                 duration: const Duration(milliseconds: 200), |   //                         isAgree ? ColorPalette.primary : ColorPalette.white, | ||||||
|                 child: Container( |   //                     shape: BoxShape.circle), | ||||||
|                   decoration: BoxDecoration( |   //               ), | ||||||
|                       color: |   //             ), | ||||||
|                           isAgree ? ColorPalette.primary : ColorPalette.white, |   //           ), | ||||||
|                       shape: BoxShape.circle), |   //         ), | ||||||
|                 ), |   //         const SizedBox( | ||||||
|               ), |   //           width: 12, | ||||||
|             ), |   //         ), | ||||||
|           ), |   //         Expanded( | ||||||
|           const SizedBox( |   //             child: Column( | ||||||
|             width: 12, |   //           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|           ), |   //           children: [ | ||||||
|           Expanded( |   //             const Text( | ||||||
|               child: Column( |   //               '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.', | ||||||
|             crossAxisAlignment: CrossAxisAlignment.start, |   //               style: TextStyle( | ||||||
|             children: [ |   //                   fontSize: 16, | ||||||
|               const Text( |   //                   fontWeight: FontWeight.w600, | ||||||
|                 '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.', |   //                   color: ColorPalette.slate400), | ||||||
|                 style: TextStyle( |   //             ), | ||||||
|                     fontSize: 16, |   //             GestureDetector( | ||||||
|                     fontWeight: FontWeight.w600, |   //                 onTap: () {}, | ||||||
|                     color: ColorPalette.slate400), |   //                 child: const Text( | ||||||
|               ), |   //                   'Read More', | ||||||
|               GestureDetector( |   //                   style: TextStyle( | ||||||
|                   onTap: () {}, |   //                       fontSize: 16, | ||||||
|                   child: const Text( |   //                       fontWeight: FontWeight.w600, | ||||||
|                     'Read More', |   //                       decoration: TextDecoration.underline, | ||||||
|                     style: TextStyle( |   //                       color: ColorPalette.primary), | ||||||
|                         fontSize: 16, |   //                 )) | ||||||
|                         fontWeight: FontWeight.w600, |   //           ], | ||||||
|                         decoration: TextDecoration.underline, |   //         )) | ||||||
|                         color: ColorPalette.primary), |   //       ], | ||||||
|                   )) |   //     ), | ||||||
|             ], |   //   ); | ||||||
|           )) |   // } | ||||||
|         ], |  | ||||||
|       ), |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import 'dart:io'; | |||||||
|  |  | ||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | 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/button/button_view.dart'; | ||||||
|  | import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | ||||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | import 'package:cims_apps/application/component/image/image_view.dart'; | ||||||
| import 'package:cims_apps/application/component/take_picture_screen/take_picture_screen.dart'; | import 'package:cims_apps/application/component/take_picture_screen/take_picture_screen.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| @@ -94,10 +95,8 @@ class _DisplayPictureScreenState extends State<DisplayPictureScreen> { | |||||||
|           return Consumer<SubmissionDataViewModel>( |           return Consumer<SubmissionDataViewModel>( | ||||||
|               builder: (context, provider, child) { |               builder: (context, provider, child) { | ||||||
|             return Scaffold( |             return Scaffold( | ||||||
|               appBar: AppBar( |               appBar: CustomAppBar( | ||||||
|                 title: const Text('Preview'), |                   height: SizeConfig.height * .08, title: 'Preview'), | ||||||
|                 automaticallyImplyLeading: false, |  | ||||||
|               ), |  | ||||||
|               body: Container( |               body: Container( | ||||||
|                   padding: const EdgeInsets.symmetric(horizontal: 24.0), |                   padding: const EdgeInsets.symmetric(horizontal: 24.0), | ||||||
|                   child: Column( |                   child: Column( | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import 'package:camera/camera.dart'; | import 'package:camera/camera.dart'; | ||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | ||||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | import 'package:cims_apps/application/component/image/image_view.dart'; | ||||||
| import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart'; | import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart'; | ||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| @@ -27,7 +28,6 @@ class TakePictureScreenState extends State<TakePictureScreen> { | |||||||
|   late String _takeContent; |   late String _takeContent; | ||||||
|  |  | ||||||
|   Future<void> changeFlash() async { |   Future<void> changeFlash() async { | ||||||
|     await _controller.setFlashMode(FlashMode.auto); |  | ||||||
|     setState(() { |     setState(() { | ||||||
|       isFlash = !isFlash; |       isFlash = !isFlash; | ||||||
|     }); |     }); | ||||||
| @@ -44,6 +44,7 @@ class TakePictureScreenState extends State<TakePictureScreen> { | |||||||
|     // Next, initialize the controller. This returns a Future. |     // Next, initialize the controller. This returns a Future. | ||||||
|     _initializeControllerFuture = _controller.initialize(); |     _initializeControllerFuture = _controller.initialize(); | ||||||
|     _takeContent = widget.takeContent; |     _takeContent = widget.takeContent; | ||||||
|  |     _controller.setFlashMode(isFlash ? FlashMode.torch : FlashMode.off); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -57,9 +58,10 @@ class TakePictureScreenState extends State<TakePictureScreen> { | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     // Fill this out in the next steps. |     // Fill this out in the next steps. | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       appBar: AppBar( |       appBar: CustomAppBar( | ||||||
|         title: const Text('Registration'), |         title: 'Registration', | ||||||
|         actions: [ |         height: SizeConfig.height * .08, | ||||||
|  |         trailing: [ | ||||||
|           IconButton( |           IconButton( | ||||||
|               onPressed: () { |               onPressed: () { | ||||||
|                 changeFlash(); |                 changeFlash(); | ||||||
|   | |||||||
| @@ -92,6 +92,7 @@ class ColorPalette { | |||||||
|   static const Color green100 = Color(0xFFDCFCE7); |   static const Color green100 = Color(0xFFDCFCE7); | ||||||
|   static const Color green400 = Color(0xFF4ADE80); |   static const Color green400 = Color(0xFF4ADE80); | ||||||
|   static const Color green500 = Color(0xFF16A34A); |   static const Color green500 = Color(0xFF16A34A); | ||||||
|  |   static const Color red600 = Color(0xffDC2626); | ||||||
|  |  | ||||||
|   static const Map<String, Color> investTypeColor = { |   static const Map<String, Color> investTypeColor = { | ||||||
|     'Money Market': purple500, |     'Money Market': purple500, | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter/services.dart'; | ||||||
|  | import 'package:intl/intl.dart'; | ||||||
|  |  | ||||||
| class StringUtils { | class StringUtils { | ||||||
|   static bool emailValidation(String email) { |   static bool emailValidation(String email) { | ||||||
|     return RegExp( |     return RegExp( | ||||||
| @@ -13,4 +18,24 @@ class StringUtils { | |||||||
|     return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})') |     return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})') | ||||||
|         .hasMatch(password); |         .hasMatch(password); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   static String formatTime(DateTime? dateTime) { | ||||||
|  |     if (dateTime != null) { | ||||||
|  |       DateFormat formatter = DateFormat('HH:mm:ss'); | ||||||
|  |       return formatter.format(dateTime); | ||||||
|  |     } | ||||||
|  |     return '--:--:--'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static void iCopyToClipboard(BuildContext context, | ||||||
|  |       {String? desc, required String text}) { | ||||||
|  |     Clipboard.setData(ClipboardData(text: text)); | ||||||
|  |     ScaffoldMessenger.of(context) | ||||||
|  |         .showSnackBar(SnackBar( | ||||||
|  |           backgroundColor: ColorPalette.primary, | ||||||
|  |           content: Text(desc ?? "Text copied to clipboard"), | ||||||
|  |         )) | ||||||
|  |         .closed | ||||||
|  |         .then((value) => ScaffoldMessenger.of(context).removeCurrentSnackBar()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -31,10 +31,11 @@ class RegistrationView extends StatelessWidget { | |||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         builder: (BuildContext context) { |         builder: (BuildContext context) { | ||||||
|  |           var flutterView = View.of(context); | ||||||
|           return Padding( |           return Padding( | ||||||
|             padding: EdgeInsets.only( |             padding: EdgeInsets.only( | ||||||
|               top: MediaQueryData.fromView( |               top: MediaQueryData.fromView( | ||||||
|                 WidgetsBinding.instance.window, |                 flutterView, | ||||||
|               ).padding.top, |               ).padding.top, | ||||||
|             ), |             ), | ||||||
|             child: const OtpView( |             child: const OtpView( | ||||||
|   | |||||||
| @@ -6,107 +6,120 @@ import 'package:cims_apps/application/theme/color_palette.dart'; | |||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| import 'package:cims_apps/core/utils/size_config.dart'; | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
| import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart'; | import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart'; | ||||||
|  | import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class ModelDataBank { | ||||||
|  |   final String? title, subtitle; | ||||||
|  |   ModelDataBank(this.title, this.subtitle); | ||||||
|  | } | ||||||
|  |  | ||||||
| class ConfirmBankAccount extends StatelessWidget { | class ConfirmBankAccount extends StatelessWidget { | ||||||
|   const ConfirmBankAccount({Key? key}) : super(key: key); |   const ConfirmBankAccount({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     List listData = [ |     final listDataBank = | ||||||
|       {'title': 'Bank Name', 'subtitle': 'Bank Mandiri'}, |         ModalRoute.of(context)!.settings.arguments as List<ModelDataBank>; | ||||||
|       {'title': 'Account Number', 'subtitle': '123002212084'}, |  | ||||||
|       {'title': 'Account Owner Name', 'subtitle': 'Muhamad Rosyidin'}, |     return ChangeNotifierProvider( | ||||||
|       {'title': 'Name on ID card', 'subtitle': 'Muhamad Rosyidin'}, |         create: (context) => SubmissionDataViewModel(), | ||||||
|     ]; |         builder: (context, child) { | ||||||
|     return Scaffold( |           return Scaffold( | ||||||
|       appBar: AppBar( |             appBar: AppBar( | ||||||
|         toolbarHeight: 70, |               toolbarHeight: 70, | ||||||
|         backgroundColor: Colors.white, |               backgroundColor: Colors.white, | ||||||
|         surfaceTintColor: Colors.white, |               surfaceTintColor: Colors.white, | ||||||
|         automaticallyImplyLeading: false, |               automaticallyImplyLeading: false, | ||||||
|         title: Row( |               title: Row( | ||||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, |                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|           children: [ |                 children: [ | ||||||
|             const BackButtonView(), |                   const BackButtonView(), | ||||||
|             const Text('Registration'), |                   const Text('Registration'), | ||||||
|             SizedBox( |                   SizedBox( | ||||||
|               width: SizeConfig.width * 0.1, |                     width: SizeConfig.width * 0.1, | ||||||
|             ) |                   ) | ||||||
|           ], |                 ], | ||||||
|         ), |               ), | ||||||
|         shape: const RoundedRectangleBorder( |               shape: const RoundedRectangleBorder( | ||||||
|             side: BorderSide(color: ColorPalette.slate200)), |                   side: BorderSide(color: ColorPalette.slate200)), | ||||||
|       ), |             ), | ||||||
|       body: SingleChildScrollView( |             body: SingleChildScrollView( | ||||||
|         padding: const EdgeInsets.all(16.0), |               padding: const EdgeInsets.all(16.0), | ||||||
|         child: SizedBox( |               child: SizedBox( | ||||||
|           height: SizeConfig.height * .85, |                 height: SizeConfig.height * .85, | ||||||
|           child: Column( |                 child: Consumer<SubmissionDataViewModel>( | ||||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, |                     builder: (context, provider, child) { | ||||||
|             crossAxisAlignment: CrossAxisAlignment.start, |                   return Column( | ||||||
|             children: [ |                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|               const TextCaption(title: 'Bank account confirmation'), |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|               SizedBox( |                     children: [ | ||||||
|                 height: SizeConfig.height * .6, |                       const TextCaption(title: 'Bank account confirmation'), | ||||||
|                 child: Column( |                       SizedBox( | ||||||
|                   mainAxisAlignment: MainAxisAlignment.start, |                         height: SizeConfig.height * .6, | ||||||
|                   crossAxisAlignment: CrossAxisAlignment.start, |  | ||||||
|                   children: [ |  | ||||||
|                     ...listData.map((e) { |  | ||||||
|                       return Padding( |  | ||||||
|                         padding: const EdgeInsets.only(bottom: 16.0), |  | ||||||
|                         child: Column( |                         child: Column( | ||||||
|                           mainAxisAlignment: MainAxisAlignment.start, |                           mainAxisAlignment: MainAxisAlignment.start, | ||||||
|                           crossAxisAlignment: CrossAxisAlignment.start, |                           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                           children: [ |                           children: [ | ||||||
|                             Text( |                             ...listDataBank.map((e) { | ||||||
|                               e['title'], |                               return Padding( | ||||||
|                               style: const TextStyle( |                                 padding: const EdgeInsets.only(bottom: 16.0), | ||||||
|                                   color: ColorPalette.slate400, fontSize: 16), |                                 child: Column( | ||||||
|                             ), |                                   mainAxisAlignment: MainAxisAlignment.start, | ||||||
|                             Text( |                                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                               e['subtitle'], |                                   children: [ | ||||||
|                               style: const TextStyle( |                                     Text( | ||||||
|                                   fontSize: 16, |                                       e.title!, | ||||||
|                                   color: ColorPalette.slate800, |                                       style: const TextStyle( | ||||||
|                                   fontWeight: FontWeight.w600), |                                           color: ColorPalette.slate400, | ||||||
|  |                                           fontSize: 16), | ||||||
|  |                                     ), | ||||||
|  |                                     Text( | ||||||
|  |                                       e.subtitle!, | ||||||
|  |                                       style: const TextStyle( | ||||||
|  |                                           fontSize: 16, | ||||||
|  |                                           color: ColorPalette.slate800, | ||||||
|  |                                           fontWeight: FontWeight.w600), | ||||||
|  |                                     ), | ||||||
|  |                                   ], | ||||||
|  |                                 ), | ||||||
|  |                               ); | ||||||
|  |                             }).toList(), | ||||||
|  |                             const ListTileView( | ||||||
|  |                               title: | ||||||
|  |                                   'Make sure your data is correct as it will affect the disbursement process', | ||||||
|                             ), |                             ), | ||||||
|                           ], |                           ], | ||||||
|                         ), |                         ), | ||||||
|                       ); |                       ), | ||||||
|                     }).toList(), |                       Row( | ||||||
|                     const ListTileView( |                         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                       title: |                         children: [ | ||||||
|                           'Make sure your data is correct as it will affect the disbursement process', |                           ButtonView( | ||||||
|                     ), |                             name: 'Recheck', | ||||||
|                   ], |                             isOutlined: true, | ||||||
|                 ), |                             width: SizeConfig.width * .42, | ||||||
|  |                             onPressed: () { | ||||||
|  |                               Navigator.pop(context); | ||||||
|  |                             }, | ||||||
|  |                           ), | ||||||
|  |                           ButtonView( | ||||||
|  |                             name: 'Confirm', | ||||||
|  |                             width: SizeConfig.width * .42, | ||||||
|  |                             onPressed: () { | ||||||
|  |                               routePush(context, | ||||||
|  |                                   page: const SubmissionParent()); | ||||||
|  |                             }, | ||||||
|  |                           ), | ||||||
|  |                         ], | ||||||
|  |                       ) | ||||||
|  |                     ], | ||||||
|  |                   ); | ||||||
|  |                 }), | ||||||
|               ), |               ), | ||||||
|               Row( |             ), | ||||||
|                 mainAxisAlignment: MainAxisAlignment.spaceBetween, |           ); | ||||||
|                 children: [ |         }); | ||||||
|                   ButtonView( |  | ||||||
|                     name: 'Recheck', |  | ||||||
|                     isOutlined: true, |  | ||||||
|                     width: SizeConfig.width * .42, |  | ||||||
|                     onPressed: () { |  | ||||||
|                       Navigator.pop(context); |  | ||||||
|                     }, |  | ||||||
|                   ), |  | ||||||
|                   ButtonView( |  | ||||||
|                     name: 'Confirm', |  | ||||||
|                     width: SizeConfig.width * .42, |  | ||||||
|                     onPressed: () { |  | ||||||
|                       routePush(context, page: const SubmissionParent()); |  | ||||||
|                     }, |  | ||||||
|                   ), |  | ||||||
|                 ], |  | ||||||
|               ) |  | ||||||
|             ], |  | ||||||
|           ), |  | ||||||
|         ), |  | ||||||
|       ), |  | ||||||
|     ); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,108 @@ | |||||||
|  | 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'; | ||||||
|  | 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/theme/color_palette.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
|  | import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class ListBankView extends StatelessWidget { | ||||||
|  |   final ValueChanged<String> onSelect; | ||||||
|  |   const ListBankView({Key? key, required this.onSelect}) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     var textTheme = Theme.of(context).textTheme; | ||||||
|  |  | ||||||
|  |     return ChangeNotifierProvider( | ||||||
|  |         create: (context) => SubmissionDataViewModel(), | ||||||
|  |         builder: (context, child) { | ||||||
|  |           return Scaffold( | ||||||
|  |             appBar: CustomAppBar( | ||||||
|  |                 height: SizeConfig.height * .1, title: 'Select Bank'), | ||||||
|  |             body: Container( | ||||||
|  |               padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||||
|  |               child: Consumer<SubmissionDataViewModel>( | ||||||
|  |                   builder: (context, provider, child) { | ||||||
|  |                 return Column( | ||||||
|  |                   children: [ | ||||||
|  |                     Row( | ||||||
|  |                       mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|  |                       children: [ | ||||||
|  |                         ImageView( | ||||||
|  |                           image: PathAssets.imgGuideBank, | ||||||
|  |                           width: SizeConfig.width * .35, | ||||||
|  |                         ), | ||||||
|  |                         Expanded( | ||||||
|  |                           child: Text( | ||||||
|  |                             'Make sure the bank you choose is a bank account in your own name ', | ||||||
|  |                             style: textTheme.bodyLarge, | ||||||
|  |                           ), | ||||||
|  |                         ) | ||||||
|  |                       ], | ||||||
|  |                     ), | ||||||
|  |                     TextFormView( | ||||||
|  |                       name: '', | ||||||
|  |                       hintText: 'Search bank', | ||||||
|  |                       ctrl: provider.ctrlBankNameSearch, | ||||||
|  |                       contentPadding: const EdgeInsets.symmetric(vertical: 0), | ||||||
|  |                       prefixIcon: const Icon( | ||||||
|  |                         Icons.search, | ||||||
|  |                         color: ColorPalette.slate500, | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                     Expanded( | ||||||
|  |                       child: SingleChildScrollView( | ||||||
|  |                         child: Column( | ||||||
|  |                           children: provider.listBank.asMap().entries.map((e) { | ||||||
|  |                             bool selectedBank = | ||||||
|  |                                 e.key.toString() == provider.idx; | ||||||
|  |                             return Card( | ||||||
|  |                               elevation: 0, | ||||||
|  |                               color: selectedBank | ||||||
|  |                                   ? ColorPalette.blue50 | ||||||
|  |                                   : Colors.white, | ||||||
|  |                               shape: const RoundedRectangleBorder( | ||||||
|  |                                 borderRadius: | ||||||
|  |                                     BorderRadius.all(Radius.circular(12)), | ||||||
|  |                               ), | ||||||
|  |                               child: ListTile( | ||||||
|  |                                 title: Text( | ||||||
|  |                                   e.value.text, | ||||||
|  |                                   style: TextStyle( | ||||||
|  |                                     fontSize: 16, | ||||||
|  |                                     fontWeight: FontWeight.w600, | ||||||
|  |                                     color: selectedBank | ||||||
|  |                                         ? ColorPalette.primary | ||||||
|  |                                         : ColorPalette.slate500, | ||||||
|  |                                   ), | ||||||
|  |                                 ), | ||||||
|  |                                 onTap: () { | ||||||
|  |                                   provider.changeBank(e.key.toString()); | ||||||
|  |                                   provider.selectBank(e.value.text); | ||||||
|  |                                 }, | ||||||
|  |                               ), | ||||||
|  |                             ); | ||||||
|  |                           }).toList(), | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                     ButtonView( | ||||||
|  |                       name: 'Select', | ||||||
|  |                       marginVertical: 8.0, | ||||||
|  |                       onPressed: () { | ||||||
|  |                         onSelect(provider.valueBank); | ||||||
|  |                         Navigator.pop(context); | ||||||
|  |                       }, | ||||||
|  |                     ), | ||||||
|  |                   ], | ||||||
|  |                 ); | ||||||
|  |               }), | ||||||
|  |             ), | ||||||
|  |           ); | ||||||
|  |         }); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,13 +1,13 @@ | |||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | 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/button/button_view.dart'; | ||||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | import 'package:cims_apps/application/component/image/image_view.dart'; | ||||||
| import 'package:cims_apps/application/component/select_form/select_form_view.dart'; |  | ||||||
| import 'package:cims_apps/application/component/text_caption/text_caption.dart'; | import 'package:cims_apps/application/component/text_caption/text_caption.dart'; | ||||||
| import 'package:cims_apps/application/component/text_form/text_form_view.dart'; | import 'package:cims_apps/application/component/text_form/text_form_view.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| import 'package:cims_apps/core/utils/size_config.dart'; | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
| import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/guide_screen.dart'; | import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/guide_screen.dart'; | ||||||
|  | import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/list_bank_view.dart'; | ||||||
| import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| @@ -19,6 +19,40 @@ class SubmitBankAccount extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |     showSearchBank(TextEditingController valueCtrl) { | ||||||
|  |       showModalBottomSheet( | ||||||
|  |         context: context, | ||||||
|  |         isScrollControlled: true, | ||||||
|  |         enableDrag: false, | ||||||
|  |         shape: const RoundedRectangleBorder( | ||||||
|  |           borderRadius: BorderRadius.vertical( | ||||||
|  |             top: Radius.zero, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         builder: (BuildContext context) { | ||||||
|  |           return StatefulBuilder( | ||||||
|  |             builder: (context, setState) { | ||||||
|  |               var flutterView = View.of(context); | ||||||
|  |               return Padding( | ||||||
|  |                 padding: EdgeInsets.only( | ||||||
|  |                   top: MediaQueryData.fromView( | ||||||
|  |                     flutterView, | ||||||
|  |                   ).padding.top, | ||||||
|  |                 ), | ||||||
|  |                 child: ListBankView( | ||||||
|  |                   onSelect: (value) { | ||||||
|  |                     setState(() { | ||||||
|  |                       valueCtrl.text = value; | ||||||
|  |                     }); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|  |               ); | ||||||
|  |             }, | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return MultiProvider( |     return MultiProvider( | ||||||
|         providers: [ |         providers: [ | ||||||
|           ChangeNotifierProvider( |           ChangeNotifierProvider( | ||||||
| @@ -29,56 +63,98 @@ class SubmitBankAccount extends StatelessWidget { | |||||||
|           return SizedBox( |           return SizedBox( | ||||||
|             child: Consumer<SubmissionDataViewModel>( |             child: Consumer<SubmissionDataViewModel>( | ||||||
|                 builder: (context, provider, child) { |                 builder: (context, provider, child) { | ||||||
|               return SingleChildScrollView( |               return SizedBox( | ||||||
|                 child: Column( |                 height: SizeConfig.height * .8, | ||||||
|                   crossAxisAlignment: CrossAxisAlignment.start, |                 child: Form( | ||||||
|                   children: [ |                   key: provider.formKeySubmitDataBank, | ||||||
|                     const TextCaption(title: 'Input your bank account data'), |                   child: Column( | ||||||
|                     SelectFormView( |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                       name: 'Bank Name', |                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                       hintText: 'Select Bank', |                     children: [ | ||||||
|                       listItem: provider.listBank, |                       const TextCaption(title: 'Input your bank account data'), | ||||||
|                       ctrl: provider.ctrlBankName, |                       TextFormView( | ||||||
|                       onSelect: (value) {}, |                         name: 'Bank Name', | ||||||
|                     ), |                         hintText: 'Select bank', | ||||||
|                     TextFormView( |                         readOnly: true, | ||||||
|                       name: 'Account Number', |                         ctrl: provider.ctrlBankName, | ||||||
|                       hintText: 'Input Account Number', |                         onTap: () { | ||||||
|                       keyboardType: TextInputType.number, |                           showSearchBank(provider.ctrlBankName); | ||||||
|                       trailingTitleWidget: SizedBox( |                         }, | ||||||
|                         width: 24, |                         suffixIcon: const Icon( | ||||||
|                         child: GestureDetector( |                           Icons.keyboard_arrow_down_outlined, | ||||||
|                           onTap: () { |                         ), | ||||||
|                             routePush(context, page: const GuideScreen()); |                         validator: (value) { | ||||||
|                           }, |                           if (value!.isEmpty) { | ||||||
|                           child: |                             return 'Field must be filled'; | ||||||
|                               const ImageView(image: PathAssets.iconQuestion), |                           } | ||||||
|  |                           return null; | ||||||
|  |                         }, | ||||||
|  |                       ), | ||||||
|  |                       TextFormView( | ||||||
|  |                         name: 'Account Number', | ||||||
|  |                         hintText: 'Input Account Number', | ||||||
|  |                         ctrl: provider.ctrlNoAccountBank, | ||||||
|  |                         keyboardType: TextInputType.number, | ||||||
|  |                         validator: (value) { | ||||||
|  |                           if (value!.isEmpty) { | ||||||
|  |                             return 'Field must be filled'; | ||||||
|  |                           } | ||||||
|  |                           return null; | ||||||
|  |                         }, | ||||||
|  |                         trailingTitleWidget: SizedBox( | ||||||
|  |                           width: 24, | ||||||
|  |                           child: GestureDetector( | ||||||
|  |                             onTap: () { | ||||||
|  |                               routePush(context, page: const GuideScreen()); | ||||||
|  |                             }, | ||||||
|  |                             child: | ||||||
|  |                                 const ImageView(image: PathAssets.iconQuestion), | ||||||
|  |                           ), | ||||||
|                         ), |                         ), | ||||||
|                       ), |                       ), | ||||||
|                     ), |                       TextFormView( | ||||||
|                     TextFormView( |                         name: 'Account Owner Name', | ||||||
|                       name: 'Account Owner Name', |                         hintText: 'Input Account Name', | ||||||
|                       hintText: 'Input Account Name', |                         ctrl: provider.ctrlNameAccountBank, | ||||||
|                     ), |                         validator: (value) { | ||||||
|                     const Text( |                           if (value!.isEmpty) { | ||||||
|                       "Make sure the account you use is in your name, not someone else's", |                             return 'Field must be filled'; | ||||||
|                       style: TextStyle( |  | ||||||
|                         color: ColorPalette.slate400, |  | ||||||
|                       ), |  | ||||||
|                     ), |  | ||||||
|                     SizedBox(height: SizeConfig.height * .08), |  | ||||||
|                     ButtonView( |  | ||||||
|                       name: 'Next', |  | ||||||
|                       onPressed: () { |  | ||||||
|                         provider.next(context).then((value) { |  | ||||||
|                           if (value) { |  | ||||||
|                             routePush(context, |  | ||||||
|                                 page: const ConfirmBankAccount()); |  | ||||||
|                           } |                           } | ||||||
|                         }); |                           return null; | ||||||
|                       }, |                         }, | ||||||
|                     ) |                       ), | ||||||
|                   ], |                       const Text( | ||||||
|  |                         "Make sure the account you use is in your name, not someone else's", | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           color: ColorPalette.slate400, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       SizedBox(height: SizeConfig.height * .08), | ||||||
|  |                       ButtonView( | ||||||
|  |                         name: 'Next', | ||||||
|  |                         onPressed: () { | ||||||
|  |                           if (provider.formKeySubmitDataBank.currentState! | ||||||
|  |                               .validate()) { | ||||||
|  |                             provider | ||||||
|  |                                 .submitDataBank( | ||||||
|  |                               bankName: provider.ctrlBankName.text, | ||||||
|  |                               accountNumber: provider.ctrlNoAccountBank.text, | ||||||
|  |                               accountName: provider.ctrlNameAccountBank.text, | ||||||
|  |                             ) | ||||||
|  |                                 .then((values) { | ||||||
|  |                               provider.next(context).then((value) { | ||||||
|  |                                 if (value) { | ||||||
|  |                                   routePush(context, | ||||||
|  |                                       page: const ConfirmBankAccount(), | ||||||
|  |                                       arguments: values); | ||||||
|  |                                 } | ||||||
|  |                               }); | ||||||
|  |                             }); | ||||||
|  |                           } | ||||||
|  |                         }, | ||||||
|  |                       ) | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|                 ), |                 ), | ||||||
|               ); |               ); | ||||||
|             }), |             }), | ||||||
|   | |||||||
| @@ -56,17 +56,24 @@ class _QuestionViewState extends State<QuestionView> { | |||||||
|           bottomNavigationBar: SizedBox( |           bottomNavigationBar: SizedBox( | ||||||
|             height: 84, |             height: 84, | ||||||
|             child: ButtonView( |             child: ButtonView( | ||||||
|  |               disabled: provider.listScore[currentPage] == 0, | ||||||
|               name: 'Next', |               name: 'Next', | ||||||
|               marginVertical: 16, |               marginVertical: 16, | ||||||
|  |               disabledBgColor: ColorPalette.slate200, | ||||||
|  |               textColor: provider.listScore[currentPage] == 0 ? ColorPalette.slate500 : Colors.white, | ||||||
|  |               backgroundColor: ColorPalette.primary, | ||||||
|               onPressed: () { |               onPressed: () { | ||||||
|                 if (currentPage > 3) { |                 if (currentPage > 3) { | ||||||
|                   int totalScore = provider.listScore |                   int totalScore = provider.listScore | ||||||
|                       .reduce((value, element) => value + element); |                       .reduce((value, element) => value + element); | ||||||
|                   provider.setTypeResult(totalScore); |                   provider.setTypeResult(totalScore); | ||||||
|                   routePush(context, |                   routePush(context, | ||||||
|                       page: ResultsView( |                     page: ResultsView( | ||||||
|                           totalScore: totalScore.toString(), |                         totalScore: totalScore, | ||||||
|                           typeResult: provider.typeResult)); |                         typeResult: provider.typeResult | ||||||
|  |                     ), | ||||||
|  |                     routeType: RouteType.pushReplace | ||||||
|  |                   ); | ||||||
|                 } else { |                 } else { | ||||||
|                   setState(() { |                   setState(() { | ||||||
|                     currentPage += 1; |                     currentPage += 1; | ||||||
|   | |||||||
| @@ -1,14 +1,17 @@ | |||||||
| import 'package:cims_apps/application/component/button/back_button_view.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/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/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| import 'package:cims_apps/core/utils/size_config.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/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:cims_apps/features/auth/registration/view/submission_data/terms_and_condition/terms_and_condition_view.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| class ResultsView extends StatelessWidget { | class ResultsView extends StatelessWidget { | ||||||
|   final String totalScore; |   final int totalScore; | ||||||
|   final RiskProfileResult typeResult; |   final RiskProfileResult typeResult; | ||||||
|   const ResultsView( |   const ResultsView( | ||||||
|       {super.key, required this.typeResult, required this.totalScore}); |       {super.key, required this.typeResult, required this.totalScore}); | ||||||
| @@ -37,115 +40,15 @@ class ResultsView extends StatelessWidget { | |||||||
|         child: Column( |         child: Column( | ||||||
|           crossAxisAlignment: CrossAxisAlignment.start, |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|           children: [ |           children: [ | ||||||
|             ClipRRect( |             RiskProfile(totalScore: totalScore, rowSuitableProduct: false), | ||||||
|               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(), |  | ||||||
|             ), |  | ||||||
|             const SizedBox( |             const SizedBox( | ||||||
|               height: 32, |               height: 32, | ||||||
|             ), |             ), | ||||||
|             ButtonView( |             ButtonView( | ||||||
|               name: 'Re-test', |               name: 'Re-test', | ||||||
|               onPressed: () {}, |               onPressed: () { | ||||||
|  |                 routePush(context, page: QuestionView(), routeType: RouteType.pushReplace); | ||||||
|  |               }, | ||||||
|               marginVertical: 0, |               marginVertical: 0, | ||||||
|               backgroundColor: ColorPalette.white, |               backgroundColor: ColorPalette.white, | ||||||
|               textColor: ColorPalette.primary, |               textColor: ColorPalette.primary, | ||||||
|   | |||||||
| @@ -14,12 +14,12 @@ class RiskProfileView extends StatelessWidget { | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Container( |     return Container( | ||||||
|       width: SizeConfig.width, |       width: SizeConfig.width, | ||||||
|       height: SizeConfig.height, |       height: SizeConfig.height * .8, | ||||||
|       padding: EdgeInsets.all(24), |       padding: const EdgeInsets.all(24), | ||||||
|       child: Column( |       child: Column( | ||||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, |         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|         children: [ |         children: [ | ||||||
|           Column( |           const Column( | ||||||
|             children: [ |             children: [ | ||||||
|               ImageView(image: PathAssets.imgDataReport), |               ImageView(image: PathAssets.imgDataReport), | ||||||
|               SizedBox( |               SizedBox( | ||||||
| @@ -48,7 +48,7 @@ class RiskProfileView extends StatelessWidget { | |||||||
|           ), |           ), | ||||||
|           Column( |           Column( | ||||||
|             children: [ |             children: [ | ||||||
|               Row( |               const Row( | ||||||
|                 mainAxisAlignment: MainAxisAlignment.center, |                 mainAxisAlignment: MainAxisAlignment.center, | ||||||
|                 children: [ |                 children: [ | ||||||
|                   ImageView( |                   ImageView( | ||||||
| @@ -68,7 +68,7 @@ class RiskProfileView extends StatelessWidget { | |||||||
|                   ) |                   ) | ||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|               SizedBox( |               const SizedBox( | ||||||
|                 height: 24, |                 height: 24, | ||||||
|               ), |               ), | ||||||
|               ButtonView( |               ButtonView( | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import 'package:cims_apps/application/component/button/back_button_view.dart'; | ||||||
| import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/route/route.dart'; | import 'package:cims_apps/core/route/route.dart'; | ||||||
| @@ -66,47 +67,55 @@ class _SubmissionParentState extends State<SubmissionParent> { | |||||||
|     return ChangeNotifierProvider( |     return ChangeNotifierProvider( | ||||||
|         create: (context) => SubmissionDataViewModel(), |         create: (context) => SubmissionDataViewModel(), | ||||||
|         builder: (context, child) { |         builder: (context, child) { | ||||||
|           return WillPopScope( |           return PopScope( | ||||||
|             onWillPop: () async { |             canPop: false, | ||||||
|  |             onPopInvoked: (didPop) async { | ||||||
|  |               if (didPop) { | ||||||
|  |                 return; | ||||||
|  |               } | ||||||
|               await routePush(context, |               await routePush(context, | ||||||
|                   page: const BottomNavigationView(), |                   page: const BottomNavigationView(), | ||||||
|                   routeType: RouteType.pushReplace); |                   routeType: RouteType.pushReplace); | ||||||
|               return false; |  | ||||||
|             }, |             }, | ||||||
|             child: Consumer<SubmissionDataViewModel>( |             child: Consumer<SubmissionDataViewModel>( | ||||||
|                 builder: (context, provider, child) { |                 builder: (context, provider, child) { | ||||||
|               return Scaffold( |               return Scaffold( | ||||||
|                 appBar: CustomAppBar( |                 appBar: CustomAppBar( | ||||||
|                     height: SizeConfig.height * .1, title: 'Registration'), |                   height: SizeConfig.height * .1, | ||||||
|                 body: Stack( |                   title: 'Registration', | ||||||
|  |                   leading: BackButtonView( | ||||||
|  |                     onPress: () { | ||||||
|  |                       routePush( | ||||||
|  |                         context, | ||||||
|  |                         page: const BottomNavigationView(), | ||||||
|  |                         routeType: RouteType.pushReplace, | ||||||
|  |                       ); | ||||||
|  |                     }, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 body: Column( | ||||||
|  |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                   children: [ |                   children: [ | ||||||
|                     Column( |                     Padding( | ||||||
|                       crossAxisAlignment: CrossAxisAlignment.start, |                       padding: const EdgeInsets.symmetric( | ||||||
|                       mainAxisAlignment: MainAxisAlignment.spaceBetween, |                           horizontal: 16.0, vertical: 16.0), | ||||||
|                       children: [ |                       child: Row( | ||||||
|                         Padding( |                         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                           padding: const EdgeInsets.symmetric( |                         children: List.generate(provider.stepAmount, (index) { | ||||||
|                               horizontal: 16.0, vertical: 16.0), |                           return _stepItem( | ||||||
|                           child: Row( |                             isCurrentStep: | ||||||
|                             mainAxisAlignment: MainAxisAlignment.spaceBetween, |                                 provider.getCurrentStep == index + 1 || | ||||||
|                             children: |                                     provider.getCurrentStep - 1 > index, | ||||||
|                                 List.generate(provider.stepAmount, (index) { |                           ); | ||||||
|                               return _stepItem( |                         }), | ||||||
|                                 isCurrentStep: |                       ), | ||||||
|                                     provider.getCurrentStep == index + 1 || |                     ), | ||||||
|                                         provider.getCurrentStep - 1 > index, |                     Expanded( | ||||||
|                               ); |                       child: SingleChildScrollView( | ||||||
|                             }), |                         padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||||
|                           ), |                         child: _content(provider.getCurrentStep), | ||||||
|                         ), |                       ), | ||||||
|                         Expanded( |  | ||||||
|                           child: Container( |  | ||||||
|                             padding: |  | ||||||
|                                 const EdgeInsets.symmetric(horizontal: 16.0), |  | ||||||
|                             child: _content(provider.getCurrentStep), |  | ||||||
|                           ), |  | ||||||
|                         ), |  | ||||||
|                       ], |  | ||||||
|                     ), |                     ), | ||||||
|                   ], |                   ], | ||||||
|                 ), |                 ), | ||||||
|   | |||||||
| @@ -176,79 +176,107 @@ class SubmitDataIdCard extends StatelessWidget { | |||||||
|           return SingleChildScrollView( |           return SingleChildScrollView( | ||||||
|             child: Consumer<SubmissionDataViewModel>( |             child: Consumer<SubmissionDataViewModel>( | ||||||
|                 builder: (context, provider, child) { |                 builder: (context, provider, child) { | ||||||
|               return Column( |               return Form( | ||||||
|                 crossAxisAlignment: CrossAxisAlignment.start, |                 key: provider.formKeySubmitIdCard, | ||||||
|                 children: [ |                 child: Column( | ||||||
|                   const TextCaption( |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                       title: 'Check your ID card data for accuracy'), |                   children: [ | ||||||
|                   TextFormView( |                     const TextCaption( | ||||||
|                     name: 'NIK', |                         title: 'Check your ID card data for accuracy'), | ||||||
|                     keyboardType: TextInputType.number, |                     TextFormView( | ||||||
|                   ), |                       name: 'NIK', | ||||||
|                   TextFormView(name: 'Full Name'), |                       keyboardType: TextInputType.number, | ||||||
|                   DatePickerView( |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|  |                     ), | ||||||
|  |                     TextFormView( | ||||||
|  |                       name: 'Full Name', | ||||||
|  |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|  |                     ), | ||||||
|  |                     DatePickerView( | ||||||
|                       name: 'Birth Date', |                       name: 'Birth Date', | ||||||
|                       ctrl: provider.ctrlBirthDate, |                       ctrl: provider.ctrlBirthDate, | ||||||
|                       maxDate: DateTime.now(), |                       maxDate: DateTime.now(), | ||||||
|                       isMultipleSelection: false, |                       isMultipleSelection: false, | ||||||
|                       enabled: true), |                       enabled: true, | ||||||
|                   photoDocument(provider), |                       validatorDate: (value) { | ||||||
|                   Container( |                         if (value!.isEmpty) { | ||||||
|                     width: SizeConfig.width, |                           return 'Field must be filled'; | ||||||
|                     padding: const EdgeInsets.symmetric(horizontal: 16.0), |                         } | ||||||
|                     margin: const EdgeInsets.symmetric(vertical: 16.0), |                         return null; | ||||||
|                     decoration: BoxDecoration( |                       }, | ||||||
|                       color: ColorPalette.blue50, |  | ||||||
|                       borderRadius: BorderRadius.circular(10), |  | ||||||
|                       border: Border.all( |  | ||||||
|                         color: ColorPalette.greyLights, |  | ||||||
|                         width: 1, |  | ||||||
|                       ), |  | ||||||
|                     ), |                     ), | ||||||
|                     child: Row( |                     photoDocument(provider), | ||||||
|                       mainAxisAlignment: MainAxisAlignment.spaceBetween, |                     Container( | ||||||
|                       children: [ |                       width: SizeConfig.width, | ||||||
|                         const ImageView( |                       padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||||
|                           image: PathAssets.iconShield, |                       margin: const EdgeInsets.symmetric(vertical: 16.0), | ||||||
|                           width: 20, |                       decoration: BoxDecoration( | ||||||
|                           height: 22, |                         color: ColorPalette.blue50, | ||||||
|  |                         borderRadius: BorderRadius.circular(10), | ||||||
|  |                         border: Border.all( | ||||||
|  |                           color: ColorPalette.greyLights, | ||||||
|  |                           width: 1, | ||||||
|                         ), |                         ), | ||||||
|                         const SizedBox( |                       ), | ||||||
|                           width: 8, |                       child: Row( | ||||||
|                         ), |                         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                         const Expanded( |                         children: [ | ||||||
|                           child: Text( |                           const ImageView( | ||||||
|                             'Will my data be safe?', |                             image: PathAssets.iconShield, | ||||||
|                             style: TextStyle( |                             width: 20, | ||||||
|                               fontWeight: FontWeight.w600, |                             height: 22, | ||||||
|                               color: ColorPalette.primary, |                           ), | ||||||
|  |                           const SizedBox( | ||||||
|  |                             width: 8, | ||||||
|  |                           ), | ||||||
|  |                           const Expanded( | ||||||
|  |                             child: Text( | ||||||
|  |                               'Will my data be safe?', | ||||||
|  |                               style: TextStyle( | ||||||
|  |                                 fontWeight: FontWeight.w600, | ||||||
|  |                                 color: ColorPalette.primary, | ||||||
|  |                               ), | ||||||
|                             ), |                             ), | ||||||
|                           ), |                           ), | ||||||
|                         ), |                           IconButton( | ||||||
|                         IconButton( |                             onPressed: () { | ||||||
|                           onPressed: () { |                               bottomSheet(); | ||||||
|                             bottomSheet(); |                             }, | ||||||
|                           }, |                             icon: const Icon( | ||||||
|                           icon: const Icon( |                               Icons.arrow_forward_ios, | ||||||
|                             Icons.arrow_forward_ios, |                               color: ColorPalette.primary, | ||||||
|                             color: ColorPalette.primary, |                               size: 20, | ||||||
|                             size: 20, |                             ), | ||||||
|                           ), |                           ) | ||||||
|                         ) |                         ], | ||||||
|                       ], |                       ), | ||||||
|                     ), |                     ), | ||||||
|                   ), |                     ButtonView( | ||||||
|                   ButtonView( |                       name: 'Next', | ||||||
|                     name: 'Next', |                       onPressed: () async { | ||||||
|                     onPressed: () async { |                         if (provider.formKeySubmitIdCard.currentState! | ||||||
|                       await provider.next(context).then((value) { |                             .validate()) { | ||||||
|                         if (value) { |                           await provider.next(context).then((value) { | ||||||
|                           routePush(context, page: const SubmissionParent()); |                             if (value) { | ||||||
|  |                               routePush(context, | ||||||
|  |                                   page: const SubmissionParent()); | ||||||
|  |                             } | ||||||
|  |                           }); | ||||||
|                         } |                         } | ||||||
|                       }); |                       }, | ||||||
|                     }, |                     ) | ||||||
|                   ) |                   ], | ||||||
|                 ], |                 ), | ||||||
|               ); |               ); | ||||||
|             }), |             }), | ||||||
|           ); |           ); | ||||||
|   | |||||||
| @@ -15,41 +15,70 @@ import 'package:provider/provider.dart'; | |||||||
| class SubmitEmail extends StatelessWidget { | class SubmitEmail extends StatelessWidget { | ||||||
|   const SubmitEmail({Key? key}) : super(key: key); |   const SubmitEmail({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|   Widget _emailVerify() { |   Widget _emailVerify(BuildContext context, SubmissionDataViewModel provider) { | ||||||
|     return Column( |     var textTheme = Theme.of(context).textTheme; | ||||||
|       children: [ |     return Padding( | ||||||
|         const ImageView(image: PathAssets.imgEmail), |       padding: const EdgeInsets.all(24.0), | ||||||
|         Align( |       child: Column( | ||||||
|           alignment: Alignment.center, |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|           child: RichText( |         children: [ | ||||||
|             textAlign: TextAlign.center, |           const TextCaption(title: 'Check your e-mail'), | ||||||
|             text: TextSpan(children: [ |           const ImageView(image: PathAssets.imgEmail), | ||||||
|               const TextSpan( |           Align( | ||||||
|                 text: |             alignment: Alignment.center, | ||||||
|                     'We have sent a verification link to your e-mail. \nPlease check your email for ', |             child: RichText( | ||||||
|                 style: TextStyle( |               textAlign: TextAlign.center, | ||||||
|                   color: Colors.black, |               text: TextSpan(children: [ | ||||||
|                   decoration: TextDecoration.none, |                 TextSpan( | ||||||
|  |                   text: | ||||||
|  |                       'We have sent a verification link to your e-mail. \nPlease check your email for ', | ||||||
|  |                   style: textTheme.displayMedium, | ||||||
|                 ), |                 ), | ||||||
|               ), |                 TextSpan( | ||||||
|               TextSpan( |                   recognizer: TapGestureRecognizer() | ||||||
|                 recognizer: TapGestureRecognizer()..onTap = () {}, |                     ..onTap = () async { | ||||||
|                 text: 'verification', |                       await provider.next(context).then((value) { | ||||||
|                 style: const TextStyle( |                         if (value) { | ||||||
|                   color: Colors.blue, |                           routePush(context, page: const SubmissionParent()); | ||||||
|  |                         } | ||||||
|  |                       }); | ||||||
|  |                     }, | ||||||
|  |                   text: 'verification', | ||||||
|  |                   style: const TextStyle( | ||||||
|  |                     color: Colors.blue, | ||||||
|  |                   ), | ||||||
|                 ), |                 ), | ||||||
|               ), |                 TextSpan( | ||||||
|               const TextSpan( |                   text: ' to \ncontinue registration.', | ||||||
|                 text: ' to \ncontinue registration.', |                   style: textTheme.displayMedium, | ||||||
|                 style: TextStyle( |  | ||||||
|                   color: Colors.black, |  | ||||||
|                   decoration: TextDecoration.none, |  | ||||||
|                 ), |                 ), | ||||||
|               ), |               ]), | ||||||
|             ]), |             ), | ||||||
|           ), |           ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   showEmailVerify(BuildContext context, SubmissionDataViewModel provider) { | ||||||
|  |     showModalBottomSheet( | ||||||
|  |       context: context, | ||||||
|  |       isScrollControlled: true, | ||||||
|  |       enableDrag: false, | ||||||
|  |       shape: const RoundedRectangleBorder( | ||||||
|  |         borderRadius: BorderRadius.vertical( | ||||||
|  |           top: Radius.zero, | ||||||
|         ), |         ), | ||||||
|       ], |       ), | ||||||
|  |       builder: (context) { | ||||||
|  |         var flutterView = View.of(context); | ||||||
|  |         return Padding( | ||||||
|  |           padding: EdgeInsets.only( | ||||||
|  |             top: MediaQueryData.fromView(flutterView).padding.top, | ||||||
|  |           ), | ||||||
|  |           child: _emailVerify(context, provider), | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -60,45 +89,41 @@ class SubmitEmail extends StatelessWidget { | |||||||
|         builder: (context, child) { |         builder: (context, child) { | ||||||
|           return Consumer<SubmissionDataViewModel>( |           return Consumer<SubmissionDataViewModel>( | ||||||
|               builder: (context, provider, child) { |               builder: (context, provider, child) { | ||||||
|             return SingleChildScrollView( |             return SizedBox( | ||||||
|               child: Column( |               height: SizeConfig.height * .78, | ||||||
|                 crossAxisAlignment: CrossAxisAlignment.start, |               child: Form( | ||||||
|                 // mainAxisAlignment: MainAxisAlignment.spaceBetween, |                 key: provider.formKeySubmitEmail, | ||||||
|                 children: [ |                 child: Column( | ||||||
|                   !provider.isEmailVerify |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                       ? const TextCaption(title: 'Enter your e-mail') |                   mainAxisAlignment: MainAxisAlignment.spaceAround, | ||||||
|                       : const TextCaption(title: 'Check your e-mail '), |                   children: [ | ||||||
|                   !provider.isEmailVerify |                     const TextCaption(title: 'Enter your e-mail'), | ||||||
|                       ? TextFormView( |                     TextFormView( | ||||||
|                           name: 'E-mail Address', |                       name: 'E-mail Address', | ||||||
|                           hintText: 'Input e-mail address', |                       hintText: 'Input e-mail address', | ||||||
|                           keyboardType: TextInputType.emailAddress, |                       keyboardType: TextInputType.emailAddress, | ||||||
|                           validator: (value) { |                       validator: (value) { | ||||||
|                             if (value!.isEmpty) { |                         if (value!.isEmpty) { | ||||||
|                               return 'Filled cannot be empty'; |                           return 'Filled cannot be empty'; | ||||||
|                             } else if (!StringUtils.emailValidation(value)) { |                         } else if (!StringUtils.emailValidation(value)) { | ||||||
|                               return 'Format email wrong'; |                           return 'Format email wrong'; | ||||||
|                             } else { |                         } else { | ||||||
|                               return null; |                           return null; | ||||||
|                             } |  | ||||||
|                           }, |  | ||||||
|                           // onTap: () { |  | ||||||
|                           //   provider.submitEmail(); |  | ||||||
|                           // }, |  | ||||||
|                         ) |  | ||||||
|                       : _emailVerify(), |  | ||||||
|                   SizedBox(height: SizeConfig.height * .42), |  | ||||||
|                   ButtonView( |  | ||||||
|                     name: 'Next', |  | ||||||
|                     onPressed: () async { |  | ||||||
|                       await provider.next(context).then((value) { |  | ||||||
|                         if (value) { |  | ||||||
|                           routePush(context, page: const SubmissionParent()); |  | ||||||
|                         } |                         } | ||||||
|                       }); |                       }, | ||||||
|                     }, |                     ), | ||||||
|                   ) |                     SizedBox(height: SizeConfig.height * .43), | ||||||
|                 ], |                     ButtonView( | ||||||
|  |                       name: 'Next', | ||||||
|  |                       onPressed: () async { | ||||||
|  |                         if (provider.formKeySubmitEmail.currentState! | ||||||
|  |                             .validate()) { | ||||||
|  |                           showEmailVerify(context, provider); | ||||||
|  |                         } | ||||||
|  |                       }, | ||||||
|  |                     ) | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|               ), |               ), | ||||||
|             ); |             ); | ||||||
|           }); |           }); | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import 'package:cims_apps/application/component/button/button_view.dart'; | |||||||
| import 'package:cims_apps/application/component/select_form/select_form_view.dart'; | import 'package:cims_apps/application/component/select_form/select_form_view.dart'; | ||||||
| import 'package:cims_apps/application/component/text_caption/text_caption.dart'; | import 'package:cims_apps/application/component/text_caption/text_caption.dart'; | ||||||
| import 'package:cims_apps/core/route/route.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/submission_parent.dart'; | import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart'; | ||||||
| import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| @@ -17,12 +18,13 @@ class SubmitPersonalData extends StatelessWidget { | |||||||
|         builder: (context, child) { |         builder: (context, child) { | ||||||
|           return Consumer<SubmissionDataViewModel>( |           return Consumer<SubmissionDataViewModel>( | ||||||
|               builder: (context, provider, child) { |               builder: (context, provider, child) { | ||||||
|             return SingleChildScrollView( |             return SizedBox( | ||||||
|  |               height: SizeConfig.height * .78, | ||||||
|               child: Form( |               child: Form( | ||||||
|                 key: provider.formKeyPersonalData, |                 key: provider.formKeyPersonalData, | ||||||
|                 child: Column( |                 child: Column( | ||||||
|                   crossAxisAlignment: CrossAxisAlignment.start, |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, |                   mainAxisAlignment: MainAxisAlignment.spaceAround, | ||||||
|                   children: [ |                   children: [ | ||||||
|                     const TextCaption(title: 'Your personal details'), |                     const TextCaption(title: 'Your personal details'), | ||||||
|                     SelectFormView( |                     SelectFormView( | ||||||
| @@ -31,6 +33,12 @@ class SubmitPersonalData extends StatelessWidget { | |||||||
|                       ctrl: provider.ctrlOccupation, |                       ctrl: provider.ctrlOccupation, | ||||||
|                       listItem: provider.listOccupation, |                       listItem: provider.listOccupation, | ||||||
|                       onSelect: (value) {}, |                       onSelect: (value) {}, | ||||||
|  |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|                     ), |                     ), | ||||||
|                     SelectFormView( |                     SelectFormView( | ||||||
|                       name: 'Income Level (IDR)', |                       name: 'Income Level (IDR)', | ||||||
| @@ -38,6 +46,12 @@ class SubmitPersonalData extends StatelessWidget { | |||||||
|                       ctrl: provider.ctrlIncome, |                       ctrl: provider.ctrlIncome, | ||||||
|                       listItem: provider.listIncome, |                       listItem: provider.listIncome, | ||||||
|                       onSelect: (value) {}, |                       onSelect: (value) {}, | ||||||
|  |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|                     ), |                     ), | ||||||
|                     SelectFormView( |                     SelectFormView( | ||||||
|                       name: 'Marital Status', |                       name: 'Marital Status', | ||||||
| @@ -45,6 +59,12 @@ class SubmitPersonalData extends StatelessWidget { | |||||||
|                       ctrl: provider.ctrlMarital, |                       ctrl: provider.ctrlMarital, | ||||||
|                       listItem: provider.listMarital, |                       listItem: provider.listMarital, | ||||||
|                       onSelect: (value) {}, |                       onSelect: (value) {}, | ||||||
|  |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|                     ), |                     ), | ||||||
|                     SelectFormView( |                     SelectFormView( | ||||||
|                       name: 'Source of Fund', |                       name: 'Source of Fund', | ||||||
| @@ -52,20 +72,28 @@ class SubmitPersonalData extends StatelessWidget { | |||||||
|                       ctrl: provider.ctrlSourceFund, |                       ctrl: provider.ctrlSourceFund, | ||||||
|                       listItem: provider.listSourceFund, |                       listItem: provider.listSourceFund, | ||||||
|                       onSelect: (value) {}, |                       onSelect: (value) {}, | ||||||
|  |                       validator: (value) { | ||||||
|  |                         if (value!.isEmpty) { | ||||||
|  |                           return 'Field must be filled'; | ||||||
|  |                         } | ||||||
|  |                         return null; | ||||||
|  |                       }, | ||||||
|                     ), |                     ), | ||||||
|                     Align( |                     // SizedBox(height: SizeConfig.height * .18), | ||||||
|                       alignment: Alignment.bottomCenter, |                     ButtonView( | ||||||
|                       child: ButtonView( |                       marginVertical: 0, | ||||||
|                         name: 'Next', |                       name: 'Next', | ||||||
|                         onPressed: () async { |                       onPressed: () async { | ||||||
|  |                         if (provider.formKeyPersonalData.currentState! | ||||||
|  |                             .validate()) { | ||||||
|                           await provider.next(context).then((value) { |                           await provider.next(context).then((value) { | ||||||
|                             if (value) { |                             if (value) { | ||||||
|                               routePush(context, |                               routePush(context, | ||||||
|                                   page: const SubmissionParent()); |                                   page: const SubmissionParent()); | ||||||
|                             } |                             } | ||||||
|                           }); |                           }); | ||||||
|                         }, |                         } | ||||||
|                       ), |                       }, | ||||||
|                     ) |                     ) | ||||||
|                   ], |                   ], | ||||||
|                 ), |                 ), | ||||||
|   | |||||||
| @@ -24,26 +24,30 @@ class InitialSignature extends StatelessWidget { | |||||||
|         builder: (context, child) { |         builder: (context, child) { | ||||||
|           return Consumer<SubmissionDataViewModel>( |           return Consumer<SubmissionDataViewModel>( | ||||||
|               builder: (context, provider, child) { |               builder: (context, provider, child) { | ||||||
|             return Column( |             return SizedBox( | ||||||
|               crossAxisAlignment: CrossAxisAlignment.start, |               height: SizeConfig.height * .8, | ||||||
|               children: [ |               child: Column( | ||||||
|                 const TextCaption(title: 'Draw your digital sign'), |                 crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                 const ImageView(image: PathAssets.frameSignature), |                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                 const ListTileView( |                 children: [ | ||||||
|                     title: |                   const TextCaption(title: 'Draw your digital sign'), | ||||||
|                         'Make sure the sign you draw is match with your ID Card'), |                   const ImageView(image: PathAssets.frameSignature), | ||||||
|                 SizedBox(height: SizeConfig.height * .07), |                   const ListTileView( | ||||||
|                 ButtonView( |                       title: | ||||||
|                   name: 'Next', |                           'Make sure the sign you draw is match with your ID Card'), | ||||||
|                   onPressed: () { |                   SizedBox(height: SizeConfig.height * .1), | ||||||
|                     provider.next(context).then((value) { |                   ButtonView( | ||||||
|                       if (value) { |                     name: 'Next', | ||||||
|                         routePush(context, page: const SubmitSignature()); |                     onPressed: () { | ||||||
|                       } |                       provider.next(context).then((value) { | ||||||
|                     }); |                         if (value) { | ||||||
|                   }, |                           routePush(context, page: const SubmitSignature()); | ||||||
|                 ) |                         } | ||||||
|               ], |                       }); | ||||||
|  |                     }, | ||||||
|  |                   ) | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|             ); |             ); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import 'package:cims_apps/application/component/button/button_view.dart'; | |||||||
| import 'package:cims_apps/application/component/set_pin_view/set_pin_view.dart'; | import 'package:cims_apps/application/component/set_pin_view/set_pin_view.dart'; | ||||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
| import 'package:cims_apps/core/route/route.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/viewmodel/submission_data_viewmodel.dart'; | import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| @@ -60,47 +61,48 @@ class TermsAndConditionView extends StatelessWidget { | |||||||
|                         ], |                         ], | ||||||
|                       ), |                       ), | ||||||
|                     ); |                     ); | ||||||
|                   }) |                   }), | ||||||
|  |                   Consumer<SubmissionDataViewModel>( | ||||||
|  |                       builder: (context, provider, child) { | ||||||
|  |                     return Padding( | ||||||
|  |                       padding: const EdgeInsets.only(top: 24.0), | ||||||
|  |                       child: Row( | ||||||
|  |                         children: [ | ||||||
|  |                           Expanded( | ||||||
|  |                               child: ButtonView( | ||||||
|  |                             name: 'Decline', | ||||||
|  |                             onPressed: () { | ||||||
|  |                               Navigator.pop(context); | ||||||
|  |                             }, | ||||||
|  |                             height: SizeConfig.height * .06, | ||||||
|  |                             marginVertical: 0, | ||||||
|  |                             backgroundColor: ColorPalette.white, | ||||||
|  |                             textColor: ColorPalette.primary, | ||||||
|  |                             isOutlined: true, | ||||||
|  |                             borderColor: ColorPalette.primary, | ||||||
|  |                           )), | ||||||
|  |                           const SizedBox(width: 16), | ||||||
|  |                           Expanded( | ||||||
|  |                               child: ButtonView( | ||||||
|  |                                   name: 'Accept', | ||||||
|  |                                   onPressed: () { | ||||||
|  |                                     provider.nextSubmission(context); | ||||||
|  |                                     routePush(context, | ||||||
|  |                                         routeType: RouteType.pushReplace, | ||||||
|  |                                         page: SetPinView( | ||||||
|  |                                           currentPin: '', | ||||||
|  |                                           submitPin: (context, pin) {}, | ||||||
|  |                                         )); | ||||||
|  |                                   }, | ||||||
|  |                                   height: SizeConfig.height * .06, | ||||||
|  |                                   marginVertical: 0)) | ||||||
|  |                         ], | ||||||
|  |                       ), | ||||||
|  |                     ); | ||||||
|  |                   }), | ||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|             bottomNavigationBar: Consumer<SubmissionDataViewModel>( |  | ||||||
|                 builder: (context, provider, child) { |  | ||||||
|               return Container( |  | ||||||
|                 height: 84, |  | ||||||
|                 padding: const EdgeInsets.symmetric(horizontal: 24), |  | ||||||
|                 child: Row( |  | ||||||
|                   children: [ |  | ||||||
|                     Expanded( |  | ||||||
|                         child: ButtonView( |  | ||||||
|                       name: 'Decline', |  | ||||||
|                       onPressed: () { |  | ||||||
|                         Navigator.pop(context); |  | ||||||
|                       }, |  | ||||||
|                       marginVertical: 16, |  | ||||||
|                       backgroundColor: ColorPalette.white, |  | ||||||
|                       textColor: ColorPalette.primary, |  | ||||||
|                       isOutlined: true, |  | ||||||
|                       borderColor: ColorPalette.primary, |  | ||||||
|                     )), |  | ||||||
|                     const SizedBox(width: 16), |  | ||||||
|                     Expanded( |  | ||||||
|                         child: ButtonView( |  | ||||||
|                             name: 'Accept', |  | ||||||
|                             onPressed: () { |  | ||||||
|                               provider.nextSubmission(context); |  | ||||||
|                               routePush(context, |  | ||||||
|                                   routeType: RouteType.pushReplace, |  | ||||||
|                                   page: SetPinView( |  | ||||||
|                                     currentPin: '', |  | ||||||
|                                     submitPin: (context, pin) {}, |  | ||||||
|                                   )); |  | ||||||
|                             }, |  | ||||||
|                             marginVertical: 16)) |  | ||||||
|                   ], |  | ||||||
|                 ), |  | ||||||
|               ); |  | ||||||
|             }), |  | ||||||
|           ); |           ); | ||||||
|         }); |         }); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import 'package:camera/camera.dart'; | import 'package:camera/camera.dart'; | ||||||
| import 'package:cims_apps/application/component/select_form/select_form_view.dart'; | import 'package:cims_apps/application/component/select_form/select_form_view.dart'; | ||||||
|  | import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/confirm_bank_account.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:shared_preferences/shared_preferences.dart'; | import 'package:shared_preferences/shared_preferences.dart'; | ||||||
|  |  | ||||||
| @@ -14,13 +15,21 @@ class SubmissionDataViewModel extends ChangeNotifier { | |||||||
|   bool _isEmailVerify = false; |   bool _isEmailVerify = false; | ||||||
|   bool get isEmailVerify => _isEmailVerify; |   bool get isEmailVerify => _isEmailVerify; | ||||||
|   var formKeyPersonalData = GlobalKey<FormState>(); |   var formKeyPersonalData = GlobalKey<FormState>(); | ||||||
|  |   var formKeySubmitEmail = GlobalKey<FormState>(); | ||||||
|  |   var formKeySubmitIdCard = GlobalKey<FormState>(); | ||||||
|  |   var formKeySubmitDataBank = GlobalKey<FormState>(); | ||||||
|   TextEditingController ctrlOccupation = TextEditingController(); |   TextEditingController ctrlOccupation = TextEditingController(); | ||||||
|   TextEditingController ctrlIncome = TextEditingController(); |   TextEditingController ctrlIncome = TextEditingController(); | ||||||
|   TextEditingController ctrlMarital = TextEditingController(); |   TextEditingController ctrlMarital = TextEditingController(); | ||||||
|   TextEditingController ctrlSourceFund = TextEditingController(); |   TextEditingController ctrlSourceFund = TextEditingController(); | ||||||
|   TextEditingController ctrlBankName = TextEditingController(); |   TextEditingController ctrlBankName = TextEditingController(); | ||||||
|  |   TextEditingController ctrlNameAccountBank = TextEditingController(); | ||||||
|  |   TextEditingController ctrlNoAccountBank = TextEditingController(); | ||||||
|  |   TextEditingController ctrlBankNameSearch = TextEditingController(); | ||||||
|   TextEditingController ctrlBirthDate = TextEditingController(); |   TextEditingController ctrlBirthDate = TextEditingController(); | ||||||
|   int step = 1; |   int step = 1; | ||||||
|  |   String? idx; | ||||||
|  |   String valueBank = ''; | ||||||
|  |  | ||||||
|   List<ItemSelectForm> listOccupation = [ |   List<ItemSelectForm> listOccupation = [ | ||||||
|     ItemSelectForm('key1', 'Student'), |     ItemSelectForm('key1', 'Student'), | ||||||
| @@ -44,11 +53,13 @@ class SubmissionDataViewModel extends ChangeNotifier { | |||||||
|   ]; |   ]; | ||||||
|  |  | ||||||
|   List<ItemSelectForm> listBank = [ |   List<ItemSelectForm> listBank = [ | ||||||
|     ItemSelectForm('key1', 'BCA'), |     ItemSelectForm('0', 'BCA'), | ||||||
|     ItemSelectForm('key2', 'BRI'), |     ItemSelectForm('1', 'BRI'), | ||||||
|     ItemSelectForm('key3', 'BNI'), |     ItemSelectForm('2', 'BNI'), | ||||||
|     ItemSelectForm('key4', 'BANK MANDIRI'), |     ItemSelectForm('3', 'BANK MANDIRI'), | ||||||
|     ItemSelectForm('key5', 'CIMB NIAGA'), |     ItemSelectForm('4', 'CIMB NIAGA'), | ||||||
|  |     ItemSelectForm('5', 'PERMATA'), | ||||||
|  |     ItemSelectForm('6', 'BANK JATENG'), | ||||||
|   ]; |   ]; | ||||||
|  |  | ||||||
|   List<ItemSelectForm> listImg = [ |   List<ItemSelectForm> listImg = [ | ||||||
| @@ -105,4 +116,31 @@ class SubmissionDataViewModel extends ChangeNotifier { | |||||||
|     } |     } | ||||||
|     notifyListeners(); |     notifyListeners(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   changeBank(String key) { | ||||||
|  |     idx = key; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   selectBank(String value) { | ||||||
|  |     valueBank = value; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   List<ModelDataBank> listDataBank = []; | ||||||
|  |  | ||||||
|  |   Future<List<ModelDataBank>?> submitDataBank( | ||||||
|  |       {required String bankName, accountNumber, accountName}) async { | ||||||
|  |     List<ModelDataBank> listResponse = [ | ||||||
|  |       ModelDataBank('Bank Name', bankName), | ||||||
|  |       ModelDataBank('Account Number', accountNumber), | ||||||
|  |       ModelDataBank('Account Owner Name', accountName), | ||||||
|  |       ModelDataBank('Name on ID card', accountName), | ||||||
|  |     ]; | ||||||
|  |     if (listResponse.first.subtitle != null) { | ||||||
|  |       // listDataBank = listResponse; | ||||||
|  |       return listResponse; | ||||||
|  |     } | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -102,7 +102,7 @@ class _InvestTypeViewState extends State<InvestTypeView> { | |||||||
|                                     onTap: () { |                                     onTap: () { | ||||||
|                                       provider.setSelectedProduct(e.value); |                                       provider.setSelectedProduct(e.value); | ||||||
|                                       routePush(context, |                                       routePush(context, | ||||||
|                                           page: ProductView(widget.title)); |                                           page: ProductView(selectedProduct: e.value)); | ||||||
|                                     }, |                                     }, | ||||||
|                                     child: Padding( |                                     child: Padding( | ||||||
|                                       padding: EdgeInsets.only( |                                       padding: EdgeInsets.only( | ||||||
|   | |||||||
| @@ -1,12 +1,8 @@ | |||||||
| import 'package:cims_apps/application/component/button/button_view.dart'; |  | ||||||
| import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | ||||||
| import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart'; | import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart'; | ||||||
| import 'package:cims_apps/application/component/subscribe/input_investment_view.dart'; | import 'package:cims_apps/application/component/subscribe/input_investment_view.dart'; | ||||||
| import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; |  | ||||||
| import 'package:cims_apps/application/component/risk_profile.dart'; | import 'package:cims_apps/application/component/risk_profile.dart'; | ||||||
| import 'package:cims_apps/application/component/text_form/text_form_view.dart'; |  | ||||||
| import 'package:cims_apps/application/theme/color_palette.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/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/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/plan/view_model/plan_view_model.dart'; | ||||||
| @@ -40,42 +36,49 @@ class _PlanViewState extends State<PlanView> { | |||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |  | ||||||
|     return Scaffold( |     return ChangeNotifierProvider( | ||||||
|       appBar: CustomAppBar(height: 70, title: 'Investment Plan'), |       create: (context) => PlanViewModel(), | ||||||
|       body: SingleChildScrollView( |       child: Scaffold( | ||||||
|         padding: EdgeInsets.all(24), |         appBar: CustomAppBar( | ||||||
|         child: Column( |           height: SizeConfig.height * 0.08, | ||||||
|           crossAxisAlignment: CrossAxisAlignment.start, |           title: 'Investment Plan', | ||||||
|           children: [ |           leading: const SizedBox(), | ||||||
|             RiskProfile( |         ), | ||||||
|               totalScore: 26, |         body: SingleChildScrollView( | ||||||
|               rowSuitableProduct: true |           padding: const EdgeInsets.all(24), | ||||||
|             ), |           child: Column( | ||||||
|             SizedBox( |             crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|               height: 32, |             children: [ | ||||||
|             ), |               const RiskProfile( | ||||||
|             Text('Your Goal in Investing', |                 totalScore: 26, | ||||||
|               style: TextStyle( |                 rowSuitableProduct: true | ||||||
|                 fontWeight: FontWeight.w700, |  | ||||||
|                 color: ColorPalette.slate800, |  | ||||||
|                 fontSize: 18 |  | ||||||
|               ), |               ), | ||||||
|             ), |               const SizedBox( | ||||||
|             SizedBox( |                 height: 32, | ||||||
|               height: 24, |               ), | ||||||
|             ), |               const Text('Your Goal in Investing', | ||||||
|             GoalInvestingView( |                 style: TextStyle( | ||||||
|               onListSelected: (p0) { |                   fontWeight: FontWeight.w700, | ||||||
|                 showModalBottomSheet( |                   color: ColorPalette.slate800, | ||||||
|                   context: context, |                   fontSize: 18 | ||||||
|                   isScrollControlled: true, |                 ), | ||||||
|                   builder: (context) { |               ), | ||||||
|                     return modalInvest(context, p0); |               const SizedBox( | ||||||
|                   }, |                 height: 24, | ||||||
|                 ); |               ), | ||||||
|               }, |               GoalInvestingView( | ||||||
|             ) |                 onListSelected: (p0) { | ||||||
|           ], |                   showModalBottomSheet( | ||||||
|  |                     context: context, | ||||||
|  |                     isScrollControlled: true, | ||||||
|  |                     builder: (context) { | ||||||
|  |                       return modalInvest(context, p0); | ||||||
|  |                     }, | ||||||
|  |                   ); | ||||||
|  |                 }, | ||||||
|  |               ) | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
| @@ -95,7 +98,7 @@ class _PlanViewState extends State<PlanView> { | |||||||
|             child: Row( |             child: Row( | ||||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, |               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|               children: [ |               children: [ | ||||||
|                 Text("It's time to invest", |                 const Text("It's time to invest", | ||||||
|                   style: TextStyle( |                   style: TextStyle( | ||||||
|                     fontSize: 16, |                     fontSize: 16, | ||||||
|                     fontWeight: FontWeight.w600 |                     fontWeight: FontWeight.w600 | ||||||
| @@ -105,17 +108,20 @@ class _PlanViewState extends State<PlanView> { | |||||||
|                   onTap: () { |                   onTap: () { | ||||||
|                     Navigator.pop(context); |                     Navigator.pop(context); | ||||||
|                   }, |                   }, | ||||||
|                   child: Icon(Icons.close_rounded) |                   child: const Icon(Icons.close_rounded) | ||||||
|                 ) |                 ) | ||||||
|               ], |               ], | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|           Divider(color: ColorPalette.slate200, height: 1), |           const Divider(color: ColorPalette.slate200, height: 1), | ||||||
|           InputInvestmentView( |           InputInvestmentView( | ||||||
|             selectedPlan: text, |             currentPlan: text, | ||||||
|  |             changePlan: () { | ||||||
|  |               Navigator.pop(context); | ||||||
|  |             }, | ||||||
|             nextMove: (value) { |             nextMove: (value) { | ||||||
|               Navigator.pop(context); |               Navigator.pop(context); | ||||||
|               int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); |               int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', '')); | ||||||
|               showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse)); |               showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse)); | ||||||
|             }, |             }, | ||||||
|           ), |           ), | ||||||
|   | |||||||
| @@ -3,9 +3,14 @@ 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/image/image_view.dart'; | ||||||
| import 'package:cims_apps/application/component/subscribe/total_payment_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/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/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:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
| class ResultOptionsProduct extends StatelessWidget { | class ResultOptionsProduct extends StatelessWidget { | ||||||
|   final int totalInvest; |   final int totalInvest; | ||||||
| @@ -19,134 +24,169 @@ class ResultOptionsProduct extends StatelessWidget { | |||||||
|       Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1) |       Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1) | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     return Container( |     return ChangeNotifierProvider( | ||||||
|       decoration: BoxDecoration( |       create: (context) => PlanViewModel(), | ||||||
|         color: Colors.white, |       child: Consumer<PlanViewModel>( | ||||||
|         borderRadius: BorderRadius.circular(16) |         builder: (context, provider, child) { | ||||||
|       ), |           return Container( | ||||||
|       padding: const EdgeInsets.all(24), |             decoration: BoxDecoration( | ||||||
|       child: Column( |               color: Colors.white, | ||||||
|         mainAxisSize: MainAxisSize.min, |               borderRadius: BorderRadius.circular(16) | ||||||
|         children: [ |             ), | ||||||
|           const Row( |             padding: const EdgeInsets.all(24), | ||||||
|             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( |  | ||||||
|             child: Column( |             child: Column( | ||||||
|               children: listProduct.asMap().entries.map((e) { |               mainAxisSize: MainAxisSize.min, | ||||||
|                 return Container( |               children: [ | ||||||
|                   margin: const EdgeInsets.only(bottom: 16), |                 Row( | ||||||
|                   padding: const EdgeInsets.all(16), |                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                   decoration: BoxDecoration( |                   children: [ | ||||||
|                       color: Colors.white, |                     GestureDetector( | ||||||
|                       border: Border.all(color: ColorPalette.slate200), |                         onTap: () { | ||||||
|                       borderRadius: BorderRadius.circular(12), |                           Navigator.pop(context); | ||||||
|                       boxShadow: const [ |                           showModalBottomSheet( | ||||||
|                         BoxShadow( |                             context: context, | ||||||
|                             color: Color(0XFF1E293B0A) |                             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( |                   child: Column( | ||||||
|                     children: [ |                     children: listProduct.asMap().entries.map((e) { | ||||||
|                       Row( |                       return Container( | ||||||
|                         children: [ |                         margin: const EdgeInsets.only(bottom: 16), | ||||||
|                           const ImageView(image: PathAssets.iconGoogle, width: 30,), |                         padding: const EdgeInsets.all(16), | ||||||
|                           const SizedBox( |                         decoration: BoxDecoration( | ||||||
|                             width: 12, |                             color: Colors.white, | ||||||
|                           ), |                             border: Border.all(color: ColorPalette.slate200), | ||||||
|                           Expanded( |                             borderRadius: BorderRadius.circular(12), | ||||||
|                             child: Column( |                             boxShadow: const [ | ||||||
|                               crossAxisAlignment: CrossAxisAlignment.start, |                               BoxShadow( | ||||||
|  |                                   color: Color(0XFF1E293B0A) | ||||||
|  |                               ) | ||||||
|  |                             ] | ||||||
|  |                         ), | ||||||
|  |                         child: Column( | ||||||
|  |                           children: [ | ||||||
|  |                             Row( | ||||||
|                               children: [ |                               children: [ | ||||||
|                                 Text(e.value.name ?? '', |                                 const ImageView(image: PathAssets.iconGoogle, width: 30,), | ||||||
|                                   style: const TextStyle( |                                 const SizedBox( | ||||||
|                                     fontWeight: FontWeight.w700, |                                   width: 12, | ||||||
|                                     color: ColorPalette.slate800, |                                 ), | ||||||
|  |                                 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,), |                                 Text('${(e.value.totalPercent! * 100).toInt()} %', | ||||||
|                                 Container( |                                   style: const TextStyle( | ||||||
|                                   padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), |                                       fontWeight: FontWeight.w700, | ||||||
|                                   decoration: BoxDecoration( |                                       fontSize: 16, | ||||||
|                                       border: Border.all(color: ColorPalette.investTypeColor[e.value.type]!), |                                       color: ColorPalette.slate800 | ||||||
|                                       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 Padding( | ||||||
|                           Text('${(e.value.totalPercent! * 100).toInt()} %', |                               padding: EdgeInsets.symmetric(vertical: 16), | ||||||
|                             style: const TextStyle( |                               child: Divider(height: 1, color: ColorPalette.slate200), | ||||||
|                                 fontWeight: FontWeight.w700, |  | ||||||
|                                 fontSize: 16, |  | ||||||
|                                 color: ColorPalette.slate800 |  | ||||||
|                             ), |                             ), | ||||||
|                           ) |                             GestureDetector( | ||||||
|                         ], |                               onTap: () { | ||||||
|                       ), |                                 routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true)); | ||||||
|                       const Padding( |                               }, | ||||||
|                         padding: EdgeInsets.symmetric(vertical: 16), |                               child: const Text('See More', | ||||||
|                         child: Divider(height: 1, color: ColorPalette.slate200), |                                 style: TextStyle( | ||||||
|                       ), |                                   color: ColorPalette.slate500, | ||||||
|                       GestureDetector( |                                   fontWeight: FontWeight.w600, | ||||||
|                         onTap: () { |                                 ), | ||||||
|                         }, |                               ), | ||||||
|                         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<PlanViewModel>( | ||||||
|  |                             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, |  | ||||||
|           ) |  | ||||||
|         ], |  | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -3,4 +3,10 @@ import 'package:flutter/material.dart'; | |||||||
|  |  | ||||||
| class PlanViewModel extends ChangeNotifier { | class PlanViewModel extends ChangeNotifier { | ||||||
|   List<Product> listProduct = []; |   List<Product> listProduct = []; | ||||||
|  |   bool isAgree = false; | ||||||
|  |  | ||||||
|  |   void setAgree() { | ||||||
|  |     isAgree = !isAgree; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -0,0 +1,265 @@ | |||||||
|  | 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/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 PortfolioDetailView extends StatelessWidget { | ||||||
|  |   const PortfolioDetailView({super.key}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     List<PortfolioProduct> listProduct = [ | ||||||
|  |       PortfolioProduct( | ||||||
|  |           name: 'Gemilang Dana Kas Maxima', | ||||||
|  |           type: 'Money Market', | ||||||
|  |           yield: 8.17, | ||||||
|  |           priceUnit: 2600.79, | ||||||
|  |           funds: 6300000, | ||||||
|  |           totalUnit: 14520 | ||||||
|  |       ), | ||||||
|  |       PortfolioProduct( | ||||||
|  |           name: 'Gemilang Dana Likuid', | ||||||
|  |           type: 'Sharia', | ||||||
|  |           yield: 6.42, | ||||||
|  |           priceUnit: 1600.79, | ||||||
|  |           funds: 2340000, | ||||||
|  |           totalUnit: 232, | ||||||
|  |       ), | ||||||
|  |       PortfolioProduct( | ||||||
|  |           name: 'Gemilang Income Fund', | ||||||
|  |           type: 'Bonds', | ||||||
|  |           yield: 8.17, | ||||||
|  |           priceUnit: 2600.79, | ||||||
|  |           funds: 6300000, | ||||||
|  |           totalUnit: 2450, | ||||||
|  |       ) | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     return 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: Container( | ||||||
|  |                       decoration: BoxDecoration( | ||||||
|  |                         borderRadius: BorderRadius.circular(12), | ||||||
|  |                         color: Colors.white, | ||||||
|  |                       ), | ||||||
|  |                       child: Consumer<RedeemProductViewModel>( | ||||||
|  |                         builder: (context, provider, child) { | ||||||
|  |                           return ListView( | ||||||
|  |                             padding: const EdgeInsets.all(24), | ||||||
|  |                             children: listProduct.asMap().entries.map((e) { | ||||||
|  |                               return cardPortfolio(context, e.value); | ||||||
|  |                             }).toList(), | ||||||
|  |                           ); | ||||||
|  |                         } | ||||||
|  |                       ), | ||||||
|  |                     ) | ||||||
|  |                   ) | ||||||
|  |                 ], | ||||||
|  |               ) | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Widget cardPortfolio(context, PortfolioProduct product) { | ||||||
|  |     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: [ | ||||||
|  |                     TextTitle(title: product.name ?? '', fontSize: 16,), | ||||||
|  |                     const SizedBox(height: 4), | ||||||
|  |                     Container( | ||||||
|  |                       padding: const EdgeInsets.all(6), | ||||||
|  |                       decoration: BoxDecoration( | ||||||
|  |                           borderRadius: BorderRadius.circular(40), | ||||||
|  |                           color: ColorPalette.investTypeBgColor[product.type!]?.withOpacity(0.5) ?? Colors.white, | ||||||
|  |                           border: Border.all(width: 2, color: ColorPalette.investTypeColor[product.type!]?.withOpacity(0.4) ?? Colors.white) | ||||||
|  |                       ), | ||||||
|  |                       child: Text( | ||||||
|  |                         product.type ?? '', | ||||||
|  |                         style: TextStyle( | ||||||
|  |                             color: ColorPalette.investTypeColor[product.type!], | ||||||
|  |                             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', NumberFormatter.numberCurrency(product.priceUnit, 'Rp ', 'id_ID')), | ||||||
|  |               rowDescription('Number of Units', '${product.totalUnit ?? 0}'), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |           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: () { | ||||||
|  |                     Provider.of<RedeemProductViewModel>(context, listen: false).setProduct(product); | ||||||
|  |                     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, | ||||||
|  |           ), | ||||||
|  |         ) | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,7 +1,10 @@ | |||||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | 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/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/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/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:fl_chart/fl_chart.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| @@ -147,9 +150,31 @@ class _PortofolioViewState extends State<PortofolioView> { | |||||||
|                         ), |                         ), | ||||||
|                         menuPortofolio(), |                         menuPortofolio(), | ||||||
|                         const SizedBox( |                         const SizedBox( | ||||||
|                           height: 24, |                           height: 12, | ||||||
|                         ), |                         ), | ||||||
|                         ...listColumnPortofolio(), |                         const Padding( | ||||||
|  |                           padding: 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), | ||||||
|  |                                   const Text('Create', | ||||||
|  |                                     style: TextStyle( | ||||||
|  |                                       color: ColorPalette.primary, | ||||||
|  |                                       fontWeight: FontWeight.w600 | ||||||
|  |                                     ), | ||||||
|  |                                   ) | ||||||
|  |                                 ], | ||||||
|  |                               ) | ||||||
|  |                             ], | ||||||
|  |                           ), | ||||||
|  |                         ), | ||||||
|  |                         // ...listColumnPortofolio(), | ||||||
|  |                         cardPortfolio() | ||||||
|                       ], |                       ], | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
| @@ -183,6 +208,7 @@ class _PortofolioViewState extends State<PortofolioView> { | |||||||
|                     seePortofolioValue |                     seePortofolioValue | ||||||
|                         ? Icons.visibility_off_outlined |                         ? Icons.visibility_off_outlined | ||||||
|                         : Icons.visibility_outlined, |                         : Icons.visibility_outlined, | ||||||
|  |                     size: 18, | ||||||
|                     color: const Color(0xff93C5FD))) |                     color: const Color(0xff93C5FD))) | ||||||
|           ], |           ], | ||||||
|         ), |         ), | ||||||
| @@ -358,4 +384,85 @@ class _PortofolioViewState extends State<PortofolioView> { | |||||||
|       ); |       ); | ||||||
|     }).toList(); |     }).toList(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Widget cardPortfolio() { | ||||||
|  |     return GestureDetector( | ||||||
|  |       onTap: () { | ||||||
|  |         routePush(context, page: const PortfolioDetailView()); | ||||||
|  |       }, | ||||||
|  |       child: Container( | ||||||
|  |         margin: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|  |         padding: const EdgeInsets.all(16), | ||||||
|  |         decoration: BoxDecoration( | ||||||
|  |           borderRadius: BorderRadius.circular(8), | ||||||
|  |           border: Border.all(color: ColorPalette.slate200) | ||||||
|  |         ), | ||||||
|  |         child: Column( | ||||||
|  |           children: [ | ||||||
|  |             Row( | ||||||
|  |               children: [ | ||||||
|  |                 Container( | ||||||
|  |                     padding: const 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 | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 const SizedBox(width: 8), | ||||||
|  |                 const Column( | ||||||
|  |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                   children: [ | ||||||
|  |                     TextTitle(title: 'Education', fontSize: 16,), | ||||||
|  |                     Text('2 Subscriptions', | ||||||
|  |                       style: TextStyle( | ||||||
|  |                         color: ColorPalette.slate400, | ||||||
|  |                         fontWeight: FontWeight.w600 | ||||||
|  |                       ), | ||||||
|  |                     ) | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |             const Padding( | ||||||
|  |               padding: EdgeInsets.symmetric(vertical: 8), | ||||||
|  |               child: Divider(height: 1, color: ColorPalette.slate200), | ||||||
|  |             ), | ||||||
|  |             const 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) | ||||||
|  |                   ], | ||||||
|  |                 ) | ||||||
|  |               ], | ||||||
|  |             ) | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,171 @@ | |||||||
|  | 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/subscribe/input_investment_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/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<ChangeAmount> createState() => _ChangeAmountState(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _ChangeAmountState extends State<ChangeAmount> { | ||||||
|  |   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<RedeemProductViewModel>( | ||||||
|  |         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,), | ||||||
|  |               Column( | ||||||
|  |                 crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                 children: [ | ||||||
|  |                   Padding( | ||||||
|  |                     padding: EdgeInsets.all(24), | ||||||
|  |                     child: cardProduct() | ||||||
|  |                   ), | ||||||
|  |                   InputInvestmentView( | ||||||
|  |                     minimumPrice: (provider.getCurrentProduct.priceUnit! * 1).toInt(), | ||||||
|  |                     maximumPrice: (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(), | ||||||
|  |                     currentPrice: provider.getAmount!.toInt(), | ||||||
|  |                     nextMove: (value) { | ||||||
|  |                       String formatValueInput = value.replaceAll('Rp ', '').replaceAll('.', ''); | ||||||
|  |                       provider.setAmount(double.parse(formatValueInput)); | ||||||
|  |                       Navigator.pop(context); | ||||||
|  |                       showModalBottomSheet( | ||||||
|  |                         context: context, | ||||||
|  |                         isScrollControlled: true, | ||||||
|  |                         builder: (context) { | ||||||
|  |                           return const RedeemProduct(); | ||||||
|  |                         }, | ||||||
|  |                       ); | ||||||
|  |                     }, | ||||||
|  |                   ) | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |               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 | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 ) | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -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<Account> listAccount = [ | ||||||
|  |       Account('Muhamad Rosyidin', 'BRI', '902139012324'), | ||||||
|  |       Account('Achmad Muhaimin', 'BCA', '21391283928') | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     return ChangeNotifierProvider( | ||||||
|  |       create: (context) => RedeemProductViewModel(), | ||||||
|  |       child: Consumer<RedeemProductViewModel>( | ||||||
|  |         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<String> 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), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,360 @@ | |||||||
|  | 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<RedeemProduct> createState() => _RedeemProductState(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _RedeemProductState extends State<RedeemProduct> { | ||||||
|  |   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<RedeemProductViewModel>( | ||||||
|  |         builder: (context, provider, child) { | ||||||
|  |           amountController.text = NumberFormatter.numberCurrency(provider.getAmount!.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.getUnit!, | ||||||
|  |                       (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<RedeemProductViewModel>(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<String> 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 | ||||||
|  |                         ), | ||||||
|  |                       ) | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ) | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |         ) | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,205 @@ | |||||||
|  | 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'; | ||||||
|  | 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<RedeemProductViewModel>( | ||||||
|  |         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: [ | ||||||
|  |                     const Text('Investment Funds that You Cash Out', | ||||||
|  |                       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: cardProduct(provider.getCurrentProduct, provider.getUnit!), | ||||||
|  |               ), | ||||||
|  |               const Padding( | ||||||
|  |                 padding: 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 | ||||||
|  |                       ), | ||||||
|  |                     ) | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               const SizedBox(height: 16), | ||||||
|  |               const Padding( | ||||||
|  |                 padding: 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 | ||||||
|  |                       ), | ||||||
|  |                     ) | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               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) | ||||||
|  |             ], | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   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 | ||||||
|  |                       ), | ||||||
|  |                     ) | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,73 @@ | |||||||
|  | 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; | ||||||
|  |  | ||||||
|  |   bool isAgree = false; | ||||||
|  |  | ||||||
|  |   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; | ||||||
|  |     amount = product.priceUnit! * (product.totalUnit! / 2.0); | ||||||
|  |     unit = (product.totalUnit! / 2.0); | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void setAgree() { | ||||||
|  |     isAgree = !isAgree; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -24,8 +24,9 @@ class Time { | |||||||
| } | } | ||||||
|  |  | ||||||
| class ProductView extends StatefulWidget { | class ProductView extends StatefulWidget { | ||||||
|   final String investType; |   final bool seeMore; | ||||||
|   const ProductView(this.investType, {super.key}); |   final Product selectedProduct; | ||||||
|  |   const ProductView({super.key, required this.selectedProduct, this.seeMore = false}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   State<ProductView> createState() => _ProductViewState(); |   State<ProductView> createState() => _ProductViewState(); | ||||||
| @@ -144,22 +145,23 @@ class _ProductViewState extends State<ProductView> { | |||||||
|             ], |             ], | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         bottomNavigationBar: Container( |         bottomNavigationBar: !widget.seeMore ? | ||||||
|           height: SizeConfig.height * .1, |           Container( | ||||||
|           padding: const EdgeInsets.symmetric(horizontal: 24), |             height: SizeConfig.height * .1, | ||||||
|           child: ButtonView( |             padding: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|             name: 'Subscribe', |             child: ButtonView( | ||||||
|             onPressed: () { |               name: 'Subscribe', | ||||||
|               showModalBottomSheet( |               onPressed: () { | ||||||
|                 context: context, |                 showModalBottomSheet( | ||||||
|                 isScrollControlled: true, |                   context: context, | ||||||
|                 builder: (context) => SelectGoalInvesting(), |                   isScrollControlled: true, | ||||||
|               ); |                   builder: (context) => SelectGoalInvesting(), | ||||||
|             }, |                 ); | ||||||
|             height: SizeConfig.height * 0.06, |               }, | ||||||
|             marginVertical: 16, |               height: SizeConfig.height * 0.06, | ||||||
|           ), |               marginVertical: 16, | ||||||
|         ), |             ), | ||||||
|  |           ) : SizedBox(), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -177,7 +179,7 @@ class _ProductViewState extends State<ProductView> { | |||||||
|                   SizedBox(width: 8), |                   SizedBox(width: 8), | ||||||
|                   Expanded( |                   Expanded( | ||||||
|                     child: Text( |                     child: Text( | ||||||
|                       'Gemilang Dana Kas Maxima', |                       widget.selectedProduct.name ?? '', | ||||||
|                       maxLines: 2, |                       maxLines: 2, | ||||||
|                       overflow: TextOverflow.ellipsis, |                       overflow: TextOverflow.ellipsis, | ||||||
|                       style: TextStyle( |                       style: TextStyle( | ||||||
| @@ -190,17 +192,18 @@ class _ProductViewState extends State<ProductView> { | |||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|  |             SizedBox(width: 12), | ||||||
|             Container( |             Container( | ||||||
|               padding: const EdgeInsets.all(6), |               padding: const EdgeInsets.all(6), | ||||||
|               decoration: BoxDecoration( |               decoration: BoxDecoration( | ||||||
|                   borderRadius: BorderRadius.circular(40), |                   borderRadius: BorderRadius.circular(40), | ||||||
|                   color: ColorPalette.investTypeBgColor[widget.investType] ?? Colors.white, |                   color: ColorPalette.investTypeBgColor[widget.selectedProduct.type] ?? Colors.white, | ||||||
|                   border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.investType] ?? Colors.white) |                   border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.selectedProduct.type] ?? Colors.white) | ||||||
|               ), |               ), | ||||||
|               child: Text( |               child: Text( | ||||||
|                 widget.investType, |                 widget.selectedProduct.type ?? '', | ||||||
|                 style: TextStyle( |                 style: TextStyle( | ||||||
|                     color: ColorPalette.investTypeColor[widget.investType], |                     color: ColorPalette.investTypeColor[widget.selectedProduct.type], | ||||||
|                     fontWeight: FontWeight.w600 |                     fontWeight: FontWeight.w600 | ||||||
|                 ), |                 ), | ||||||
|               ), |               ), | ||||||
|   | |||||||
| @@ -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/input_investment_view.dart'; | ||||||
| import 'package:cims_apps/application/component/subscribe/total_payment_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/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:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| @@ -11,10 +12,9 @@ class SelectGoalInvesting extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return MultiProvider( |  | ||||||
|       providers: [ |     return ChangeNotifierProvider( | ||||||
|         ChangeNotifierProvider(create: (context) => ProductViewModel(),) |       create: (context) => ProductViewModel(), | ||||||
|       ], |  | ||||||
|       child: Consumer<ProductViewModel>( |       child: Consumer<ProductViewModel>( | ||||||
|         builder: (context, provider, child) { |         builder: (context, provider, child) { | ||||||
|           return Container( |           return Container( | ||||||
| @@ -51,23 +51,50 @@ class SelectGoalInvesting extends StatelessWidget { | |||||||
|                       context: context, |                       context: context, | ||||||
|                       isScrollControlled: true, |                       isScrollControlled: true, | ||||||
|                       builder: (context) { |                       builder: (context) { | ||||||
|                         return InputInvestmentView( |                         return ChangeNotifierProvider( | ||||||
|                           selectedPlan: p0, |                           create: (context) => ProductViewModel(), | ||||||
|                           nextMove: (value) { |                           child: Consumer<ProductViewModel>( | ||||||
|                             Navigator.pop(context); |                             builder: (context, provider, child) { | ||||||
|                             int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); |                               return Padding( | ||||||
|                             showModalBottomSheet( |                                 padding: EdgeInsets.symmetric(vertical: 16), | ||||||
|                               context: context, |                                 child: InputInvestmentView( | ||||||
|                               isScrollControlled: true, |                                   currentPlan: p0, | ||||||
|                               builder: (context) => |                                   changePlan: () { | ||||||
|                                 TotalPaymentView( |                                     Navigator.pop(context); | ||||||
|                                   listProduct: [ |                                     showModalBottomSheet( | ||||||
|                                     provider.getSelectedProduct |                                       context: context, | ||||||
|                                   ], |                                       isScrollControlled: true, | ||||||
|                                   totalInvest: formatIntParse, |                                       builder: (context) => SelectGoalInvesting(), | ||||||
|                                 ) |                                     ); | ||||||
|                             ); |                                   }, | ||||||
|                           }, |                                   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<ProductViewModel>( | ||||||
|  |                                               builder: (context, provider, child) { | ||||||
|  |                                                 return TotalPaymentView( | ||||||
|  |                                                   listProduct: [ | ||||||
|  |                                                     provider.getSelectedProduct | ||||||
|  |                                                   ], | ||||||
|  |                                                   totalInvest: formatIntParse, | ||||||
|  |                                                   isAgree: provider.isAgree, | ||||||
|  |                                                   onTapAgree: provider.setAgree, | ||||||
|  |                                                 ); | ||||||
|  |                                               } | ||||||
|  |                                             ), | ||||||
|  |                                           ) | ||||||
|  |                                     ); | ||||||
|  |                                   }, | ||||||
|  |                                 ), | ||||||
|  |                               ); | ||||||
|  |                             } | ||||||
|  |                           ), | ||||||
|                         ); |                         ); | ||||||
|                       }, |                       }, | ||||||
|                     ); |                     ); | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ class ProductViewModel extends ChangeNotifier { | |||||||
|   Product get getSelectedProduct => selectedProduct; |   Product get getSelectedProduct => selectedProduct; | ||||||
|  |  | ||||||
|   double totalInvestment = 0; |   double totalInvestment = 0; | ||||||
|  |   bool isAgree = false; | ||||||
|  |  | ||||||
|   void setSelectedProduct(Product product) { |   void setSelectedProduct(Product product) { | ||||||
|     selectedProduct = product; |     selectedProduct = product; | ||||||
| @@ -24,4 +25,9 @@ class ProductViewModel extends ChangeNotifier { | |||||||
|     totalInvestment = value; |     totalInvestment = value; | ||||||
|     notifyListeners(); |     notifyListeners(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void setAgree() { | ||||||
|  |     isAgree = !isAgree; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -44,7 +44,6 @@ class DashboardPublicView extends StatelessWidget { | |||||||
|           return Scaffold( |           return Scaffold( | ||||||
|             body: SingleChildScrollView( |             body: SingleChildScrollView( | ||||||
|               padding: const EdgeInsets.only( |               padding: const EdgeInsets.only( | ||||||
|                 top: 32.0, |  | ||||||
|                 bottom: 8.0, |                 bottom: 8.0, | ||||||
|                 left: 24.0, |                 left: 24.0, | ||||||
|                 right: 24.0, |                 right: 24.0, | ||||||
| @@ -55,6 +54,7 @@ class DashboardPublicView extends StatelessWidget { | |||||||
|                   crossAxisAlignment: CrossAxisAlignment.start, |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, |                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                   children: [ |                   children: [ | ||||||
|  |                     SizedBox(height: SizeConfig.height * .06), | ||||||
|                     ImageView( |                     ImageView( | ||||||
|                       image: PathAssets.icon1, |                       image: PathAssets.icon1, | ||||||
|                       width: SizeConfig.width * .35, |                       width: SizeConfig.width * .35, | ||||||
| @@ -67,7 +67,7 @@ class DashboardPublicView extends StatelessWidget { | |||||||
|                       alignment: Alignment.center, |                       alignment: Alignment.center, | ||||||
|                       child: ImageView( |                       child: ImageView( | ||||||
|                         image: PathAssets.imgDashboard, |                         image: PathAssets.imgDashboard, | ||||||
|                         width: SizeConfig.width * .7, |                         width: SizeConfig.width * .8, | ||||||
|                       ), |                       ), | ||||||
|                     ), |                     ), | ||||||
|                     Row( |                     Row( | ||||||
| @@ -105,7 +105,7 @@ class DashboardPublicView extends StatelessWidget { | |||||||
|                         provider.loginGoogle(context); |                         provider.loginGoogle(context); | ||||||
|                       }, |                       }, | ||||||
|                     ), |                     ), | ||||||
|                     SizedBox(height: SizeConfig.height * .15), |                     SizedBox(height: SizeConfig.height * .1), | ||||||
|                     Row( |                     Row( | ||||||
|                       mainAxisAlignment: MainAxisAlignment.spaceBetween, |                       mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|                       children: [ |                       children: [ | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								lib/features/profile/model/list_menu_model.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,8 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class ListMenuModel { | ||||||
|  |   final String title, pathAsset; | ||||||
|  |   final Widget page; | ||||||
|  |   ListMenuModel( | ||||||
|  |       {required this.title, required this.pathAsset, required this.page}); | ||||||
|  | } | ||||||
| @@ -1,5 +1,8 @@ | |||||||
| import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | 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:cims_apps/core/utils/size_config.dart'; | ||||||
|  | import 'package:cims_apps/features/profile/model/list_menu_model.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| class ProfileView extends StatelessWidget { | class ProfileView extends StatelessWidget { | ||||||
| @@ -7,8 +10,110 @@ class ProfileView extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |     List<ListMenuModel> listMenuGeneral = [ | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'Personal Data', | ||||||
|  |           pathAsset: PathAssets.iconProfile, | ||||||
|  |           page: Container()), | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'Change Password', | ||||||
|  |           pathAsset: PathAssets.iconLock, | ||||||
|  |           page: Container()), | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'Add Card', pathAsset: PathAssets.iconCard, page: Container()), | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'Settings', | ||||||
|  |           pathAsset: PathAssets.iconSetting, | ||||||
|  |           page: Container()), | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     List<ListMenuModel> listMenuPreferences = [ | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'FAQs', pathAsset: PathAssets.iconChat, page: Container()), | ||||||
|  |       ListMenuModel( | ||||||
|  |           title: 'Log Out', | ||||||
|  |           pathAsset: PathAssets.iconLogout, | ||||||
|  |           page: Container()), | ||||||
|  |     ]; | ||||||
|  |     TextStyle textStyle = const TextStyle( | ||||||
|  |       fontSize: 20, | ||||||
|  |       fontWeight: FontWeight.bold, | ||||||
|  |       color: Colors.white, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     Widget cardContent( | ||||||
|  |         {required String title, required List<ListMenuModel> listMenu}) { | ||||||
|  |       return Container( | ||||||
|  |         width: SizeConfig.width, | ||||||
|  |         padding: const EdgeInsets.all(16.0), | ||||||
|  |         decoration: const BoxDecoration( | ||||||
|  |             color: Colors.white, | ||||||
|  |             borderRadius: BorderRadius.all(Radius.circular(12))), | ||||||
|  |         child: Column( | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |           children: [ | ||||||
|  |             Text(title), | ||||||
|  |             ...listMenu.map((e) { | ||||||
|  |               return Padding( | ||||||
|  |                 padding: const EdgeInsets.only(top: 8.0), | ||||||
|  |                 child: ListTile( | ||||||
|  |                   title: Text(e.title), | ||||||
|  |                   contentPadding: EdgeInsets.zero, | ||||||
|  |                   leading: ImageView( | ||||||
|  |                       image: e.pathAsset, width: SizeConfig.width * .08), | ||||||
|  |                   trailing: const Icon(Icons.arrow_forward_ios, | ||||||
|  |                       color: ColorPalette.slate400), | ||||||
|  |                   onTap: () { | ||||||
|  |                     // routePush(context, page: e.page); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|  |               ); | ||||||
|  |             }), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       appBar: CustomAppBar(height: SizeConfig.height * .1, title: 'Profile'), |       appBar: null, | ||||||
|  |       body: Stack( | ||||||
|  |         children: [ | ||||||
|  |           ImageView(image: PathAssets.bgProfile, width: SizeConfig.width), | ||||||
|  |           Container( | ||||||
|  |             width: SizeConfig.width, | ||||||
|  |             padding: const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0), | ||||||
|  |             child: SingleChildScrollView( | ||||||
|  |               padding: const EdgeInsets.only(bottom: 60.0), | ||||||
|  |               child: Column( | ||||||
|  |                 crossAxisAlignment: CrossAxisAlignment.center, | ||||||
|  |                 children: [ | ||||||
|  |                   Text('Profile', style: textStyle), | ||||||
|  |                   Padding( | ||||||
|  |                     padding: const EdgeInsets.only(top: 40.0, bottom: 8.0), | ||||||
|  |                     child: ImageView( | ||||||
|  |                       image: PathAssets.imgCatOutlined, | ||||||
|  |                       width: SizeConfig.width * .28, | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                   Text('Muhamad Rosyidin', | ||||||
|  |                       style: textStyle.copyWith(fontSize: 24)), | ||||||
|  |                   Text('Investor Conservative', | ||||||
|  |                       style: textStyle.copyWith( | ||||||
|  |                         fontSize: 16, | ||||||
|  |                         fontWeight: FontWeight.normal, | ||||||
|  |                         color: ColorPalette.green400, | ||||||
|  |                       )), | ||||||
|  |                   SizedBox(height: SizeConfig.height * .02), | ||||||
|  |                   cardContent(title: 'General', listMenu: listMenuGeneral), | ||||||
|  |                   SizedBox(height: SizeConfig.height * .03), | ||||||
|  |                   cardContent( | ||||||
|  |                       title: 'Preference', listMenu: listMenuPreferences), | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								lib/features/transaction/view/cancel_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,51 @@ | |||||||
|  | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart'; | ||||||
|  | import 'package:cims_apps/core/route/route.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/number_formatter.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/string_utils.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class CancelView extends StatelessWidget { | ||||||
|  |   const CancelView({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SingleChildScrollView( | ||||||
|  |       child: Consumer<TransactionViewModel>( | ||||||
|  |         builder: (context, provider, child) => Column( | ||||||
|  |           children: [ | ||||||
|  |             if (provider.listCancelTransaction.isEmpty) | ||||||
|  |               EmptyCardTransaction( | ||||||
|  |                 onPressedButton: () {}, | ||||||
|  |               ), | ||||||
|  |             ...provider.listCancelTransaction.map((e) { | ||||||
|  |               return CardTransactionView( | ||||||
|  |                 onTap: () { | ||||||
|  |                   routePush(context, | ||||||
|  |                       page: const SubscribeDetailView( | ||||||
|  |                         type: 'virtual', | ||||||
|  |                       )); | ||||||
|  |                 }, | ||||||
|  |                 iconPath: PathAssets.iconEducation, | ||||||
|  |                 type: 'Education', | ||||||
|  |                 amount: NumberFormatter.numberCurrency( | ||||||
|  |                   6000000, | ||||||
|  |                   'Rp ', | ||||||
|  |                   'id_ID', | ||||||
|  |                   decimalDigits: 0, | ||||||
|  |                 ), | ||||||
|  |                 timeTransaction: StringUtils.formatTime(DateTime.now()), | ||||||
|  |                 subs: '3 Subscription', | ||||||
|  |                 step: 'cancel', | ||||||
|  |               ); | ||||||
|  |             }), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								lib/features/transaction/view/done_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,53 @@ | |||||||
|  | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart'; | ||||||
|  | import 'package:cims_apps/core/route/route.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/number_formatter.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/string_utils.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class DoneView extends StatelessWidget { | ||||||
|  |   const DoneView({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SingleChildScrollView( | ||||||
|  |       child: Consumer<TransactionViewModel>( | ||||||
|  |         builder: (context, provider, child) { | ||||||
|  |           return Column( | ||||||
|  |             children: [ | ||||||
|  |               if (provider.listDoneTransaction.isEmpty) | ||||||
|  |                 EmptyCardTransaction( | ||||||
|  |                   onPressedButton: () {}, | ||||||
|  |                 ), | ||||||
|  |               ...provider.listDoneTransaction.map((e) { | ||||||
|  |                 return CardTransactionView( | ||||||
|  |                   onTap: () { | ||||||
|  |                     routePush(context, | ||||||
|  |                         page: const SubscribeDetailView( | ||||||
|  |                           type: 'virtual', | ||||||
|  |                         )); | ||||||
|  |                   }, | ||||||
|  |                   iconPath: PathAssets.iconEducation, | ||||||
|  |                   type: 'Education', | ||||||
|  |                   amount: NumberFormatter.numberCurrency( | ||||||
|  |                     6000000, | ||||||
|  |                     'Rp ', | ||||||
|  |                     'id_ID', | ||||||
|  |                     decimalDigits: 0, | ||||||
|  |                   ), | ||||||
|  |                   timeTransaction: StringUtils.formatTime(DateTime.now()), | ||||||
|  |                   subs: '3 Subscription', | ||||||
|  |                   step: 'done', | ||||||
|  |                 ); | ||||||
|  |               }), | ||||||
|  |             ], | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								lib/features/transaction/view/onprocess_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,50 @@ | |||||||
|  | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart'; | ||||||
|  | import 'package:cims_apps/core/route/route.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/number_formatter.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/string_utils.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class OnProcessView extends StatelessWidget { | ||||||
|  |   const OnProcessView({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SingleChildScrollView( | ||||||
|  |       child: | ||||||
|  |           Consumer<TransactionViewModel>(builder: (context, provider, child) { | ||||||
|  |         return Column(children: [ | ||||||
|  |           if (provider.listOnProcessTransaction.isEmpty) | ||||||
|  |             EmptyCardTransaction( | ||||||
|  |               onPressedButton: () {}, | ||||||
|  |             ), | ||||||
|  |           ...provider.listOnProcessTransaction.map((e) { | ||||||
|  |             return CardTransactionView( | ||||||
|  |               onTap: () { | ||||||
|  |                 routePush(context, | ||||||
|  |                     page: const SubscribeDetailView( | ||||||
|  |                       type: 'virtual', | ||||||
|  |                     )); | ||||||
|  |               }, | ||||||
|  |               iconPath: PathAssets.iconHome, | ||||||
|  |               type: 'Home', | ||||||
|  |               amount: NumberFormatter.numberCurrency( | ||||||
|  |                 6000000, | ||||||
|  |                 'Rp ', | ||||||
|  |                 'id_ID', | ||||||
|  |                 decimalDigits: 0, | ||||||
|  |               ), | ||||||
|  |               timeTransaction: StringUtils.formatTime(DateTime.now()), | ||||||
|  |               subs: '3 Subscription', | ||||||
|  |               step: 'on process', | ||||||
|  |             ); | ||||||
|  |           }), | ||||||
|  |         ]); | ||||||
|  |       }), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										516
									
								
								lib/features/transaction/view/subscribe_detail_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,516 @@ | |||||||
|  | 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/list_tile/list_tile_view.dart'; | ||||||
|  | import 'package:cims_apps/application/theme/color_palette.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/size_config.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/string_utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class SubscribeDetailView extends StatelessWidget { | ||||||
|  |   final String type; | ||||||
|  |   const SubscribeDetailView({Key? key, required this.type}) : super(key: key); | ||||||
|  |  | ||||||
|  |   Widget _stepper( | ||||||
|  |     TextTheme textTheme, { | ||||||
|  |     required String description, | ||||||
|  |     String? date, | ||||||
|  |     time, | ||||||
|  |     bool isActive = false, | ||||||
|  |     bool isDone = false, | ||||||
|  |     bool isLast = false, | ||||||
|  |   }) { | ||||||
|  |     return Container( | ||||||
|  |       padding: const EdgeInsets.only(top: 8.0, left: 16.0), | ||||||
|  |       child: Row( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Column( | ||||||
|  |             children: [ | ||||||
|  |               Padding( | ||||||
|  |                 padding: const EdgeInsets.only(left: 2.0, top: 8.0), | ||||||
|  |                 child: Icon( | ||||||
|  |                   Icons.circle_rounded, | ||||||
|  |                   size: 10, | ||||||
|  |                   color: isDone | ||||||
|  |                       ? ColorPalette.primary | ||||||
|  |                       : isActive | ||||||
|  |                           ? ColorPalette.primary | ||||||
|  |                           : ColorPalette.slate400, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               if (!isLast) | ||||||
|  |                 ConstrainedBox( | ||||||
|  |                   constraints: BoxConstraints.expand( | ||||||
|  |                       height: SizeConfig.width * .2, width: 0.0), | ||||||
|  |                   child: Padding( | ||||||
|  |                     padding: const EdgeInsets.symmetric(vertical: 4.0), | ||||||
|  |                     child: VerticalDivider( | ||||||
|  |                       color: | ||||||
|  |                           isDone ? ColorPalette.primary : ColorPalette.slate400, | ||||||
|  |                       thickness: 2.0, | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.only(left: 16.0), | ||||||
|  |             child: Column( | ||||||
|  |               crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |               children: [ | ||||||
|  |                 Padding( | ||||||
|  |                   padding: const EdgeInsets.only(bottom: 8.0), | ||||||
|  |                   child: Text( | ||||||
|  |                     description, | ||||||
|  |                     style: TextStyle( | ||||||
|  |                       fontSize: 16, | ||||||
|  |                       fontWeight: FontWeight.w600, | ||||||
|  |                       color: isDone | ||||||
|  |                           ? Colors.black87 | ||||||
|  |                           : isActive | ||||||
|  |                               ? ColorPalette.primary | ||||||
|  |                               : ColorPalette.slate400, | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 isDone | ||||||
|  |                     ? Row( | ||||||
|  |                         children: [ | ||||||
|  |                           Text(date ?? ''), | ||||||
|  |                           const Padding( | ||||||
|  |                             padding: EdgeInsets.symmetric(horizontal: 4.0), | ||||||
|  |                             child: Icon( | ||||||
|  |                               Icons.circle, | ||||||
|  |                               size: 6, | ||||||
|  |                               color: ColorPalette.slate400, | ||||||
|  |                             ), | ||||||
|  |                           ), | ||||||
|  |                           Text(time ?? ''), | ||||||
|  |                         ], | ||||||
|  |                       ) | ||||||
|  |                     : const SizedBox(), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Widget _listProduct(BuildContext context) { | ||||||
|  |     TextTheme textTheme = Theme.of(context).textTheme; | ||||||
|  |     return Padding( | ||||||
|  |       padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), | ||||||
|  |       child: Column( | ||||||
|  |         children: [ | ||||||
|  |           Row( | ||||||
|  |             children: [ | ||||||
|  |               ImageView( | ||||||
|  |                 image: PathAssets.imgProduct, | ||||||
|  |                 width: SizeConfig.width * .1, | ||||||
|  |               ), | ||||||
|  |               Padding( | ||||||
|  |                 padding: const EdgeInsets.only(left: 8.0), | ||||||
|  |                 child: Column( | ||||||
|  |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                   children: [ | ||||||
|  |                     Text( | ||||||
|  |                       'Gemilang Dana Kas Maxima', | ||||||
|  |                       style: textTheme.headlineSmall, | ||||||
|  |                     ), | ||||||
|  |                     Container( | ||||||
|  |                         padding: const EdgeInsets.symmetric( | ||||||
|  |                             horizontal: 8.0, vertical: 2.0), | ||||||
|  |                         decoration: BoxDecoration( | ||||||
|  |                           color: ColorPalette.purple100, | ||||||
|  |                           border: Border.all( | ||||||
|  |                             width: 1, | ||||||
|  |                             color: ColorPalette.purple, | ||||||
|  |                           ), | ||||||
|  |                           borderRadius: | ||||||
|  |                               const BorderRadius.all(Radius.circular(24)), | ||||||
|  |                         ), | ||||||
|  |                         child: const Text( | ||||||
|  |                           'Money Market', | ||||||
|  |                           style: TextStyle( | ||||||
|  |                             color: ColorPalette.purple500, | ||||||
|  |                           ), | ||||||
|  |                         )), | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.symmetric(vertical: 8.0), | ||||||
|  |             child: Row( | ||||||
|  |               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|  |               children: [ | ||||||
|  |                 const Text('Investment Amount'), | ||||||
|  |                 Text( | ||||||
|  |                   'Rp 2.000.000', | ||||||
|  |                   style: textTheme.headlineSmall, | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Divider( | ||||||
|  |             color: ColorPalette.slate200, | ||||||
|  |           ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Widget _cardVA(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       margin: const EdgeInsets.only(top: 16.0, bottom: 8.0), | ||||||
|  |       padding: const EdgeInsets.only(bottom: 16.0), | ||||||
|  |       decoration: BoxDecoration( | ||||||
|  |         color: Colors.white, | ||||||
|  |         border: Border.all(width: 1, color: ColorPalette.slate200), | ||||||
|  |         borderRadius: const BorderRadius.all(Radius.circular(12)), | ||||||
|  |       ), | ||||||
|  |       child: Padding( | ||||||
|  |         padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||||
|  |         child: Column( | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |           children: [ | ||||||
|  |             SizedBox(height: SizeConfig.height * .02), | ||||||
|  |             RichText( | ||||||
|  |                 text: const TextSpan(children: [ | ||||||
|  |               TextSpan( | ||||||
|  |                 text: 'Transfer to  ', | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: ColorPalette.slate400, | ||||||
|  |                   fontWeight: FontWeight.normal, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               TextSpan( | ||||||
|  |                 text: 'ABC Virtual Account', | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: ColorPalette.slate800, | ||||||
|  |                   fontWeight: FontWeight.bold, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ])), | ||||||
|  |             SizedBox(height: SizeConfig.height * .01), | ||||||
|  |             const Text( | ||||||
|  |               'Ferdy Maulana', | ||||||
|  |               style: TextStyle( | ||||||
|  |                 color: Colors.black87, | ||||||
|  |                 fontSize: 16, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             ListTileView( | ||||||
|  |               title: '8785 0000 3165 5512', | ||||||
|  |               prefixIcon: const SizedBox(), | ||||||
|  |               padding: const EdgeInsets.only(right: 16.0), | ||||||
|  |               margin: const EdgeInsets.only(top: 8.0, bottom: 8.0), | ||||||
|  |               textStyle: const TextStyle( | ||||||
|  |                   fontWeight: FontWeight.bold, color: ColorPalette.primary), | ||||||
|  |               suffixIcon: ButtonView( | ||||||
|  |                 name: 'Copy', | ||||||
|  |                 width: SizeConfig.width * .3, | ||||||
|  |                 height: SizeConfig.height * .052, | ||||||
|  |                 sizeBorderRadius: 8.0, | ||||||
|  |                 widthPrefix: 8.0, | ||||||
|  |                 marginVertical: 10.0, | ||||||
|  |                 prefixIcon: const Icon( | ||||||
|  |                   Icons.file_copy_outlined, | ||||||
|  |                   color: Colors.white, | ||||||
|  |                   size: 20, | ||||||
|  |                 ), | ||||||
|  |                 onPressed: () { | ||||||
|  |                   StringUtils.iCopyToClipboard( | ||||||
|  |                     context, | ||||||
|  |                     text: '8785 0000 3165 5512', | ||||||
|  |                   ); | ||||||
|  |                 }, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             const Divider(color: ColorPalette.slate200), | ||||||
|  |             const Text( | ||||||
|  |               'Amount to be transferred', | ||||||
|  |               style: TextStyle( | ||||||
|  |                 color: Colors.black87, | ||||||
|  |                 fontSize: 16, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             ListTileView( | ||||||
|  |               title: 'Rp 10.000.000', | ||||||
|  |               prefixIcon: const SizedBox(), | ||||||
|  |               padding: const EdgeInsets.only(right: 16.0), | ||||||
|  |               margin: const EdgeInsets.only(top: 8.0), | ||||||
|  |               textStyle: const TextStyle( | ||||||
|  |                   fontWeight: FontWeight.bold, color: ColorPalette.primary), | ||||||
|  |               suffixIcon: ButtonView( | ||||||
|  |                 name: 'Copy', | ||||||
|  |                 width: SizeConfig.width * .3, | ||||||
|  |                 height: SizeConfig.height * .052, | ||||||
|  |                 sizeBorderRadius: 8.0, | ||||||
|  |                 widthPrefix: 8.0, | ||||||
|  |                 marginVertical: 10.0, | ||||||
|  |                 prefixIcon: const Icon( | ||||||
|  |                   Icons.file_copy_outlined, | ||||||
|  |                   color: Colors.white, | ||||||
|  |                   size: 20, | ||||||
|  |                 ), | ||||||
|  |                 onPressed: () { | ||||||
|  |                   StringUtils.iCopyToClipboard( | ||||||
|  |                     context, | ||||||
|  |                     text: '10.000.000', | ||||||
|  |                   ); | ||||||
|  |                 }, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Widget _cardContent(BuildContext context) { | ||||||
|  |     TextTheme textTheme = Theme.of(context).textTheme; | ||||||
|  |     List mySteps = const [ | ||||||
|  |       { | ||||||
|  |         'desc': 'Payment Being Verified', | ||||||
|  |         'date': '07 Feb 2024 ', | ||||||
|  |         'time': '21:01', | ||||||
|  |         'isActive': false, | ||||||
|  |         'isDone': true, | ||||||
|  |         'isLast': false, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         'desc': 'Successful Payment', | ||||||
|  |         'date': '07 Feb 2024 ', | ||||||
|  |         'time': '21:01', | ||||||
|  |         'isActive': true, | ||||||
|  |         'isDone': false, | ||||||
|  |         'isLast': false, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         'desc': 'Investment Manager Verification', | ||||||
|  |         'date': '07 Feb 2024 ', | ||||||
|  |         'time': '21:01', | ||||||
|  |         'isActive': false, | ||||||
|  |         'isDone': false, | ||||||
|  |         'isLast': false, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         'desc': 'Successful Purchase', | ||||||
|  |         'date': '07 Feb 2024 ', | ||||||
|  |         'time': '21:01', | ||||||
|  |         'isActive': false, | ||||||
|  |         'isDone': false, | ||||||
|  |         'isLast': true, | ||||||
|  |       }, | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     return SingleChildScrollView( | ||||||
|  |       padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||||
|  |       child: Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Row( | ||||||
|  |             mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |             children: [ | ||||||
|  |               const Icon(Icons.access_time, color: ColorPalette.slate400), | ||||||
|  |               const Padding( | ||||||
|  |                 padding: EdgeInsets.symmetric(horizontal: 8.0), | ||||||
|  |                 child: Text('Waiting for Payment'), | ||||||
|  |               ), | ||||||
|  |               Text('23:56:42', style: textTheme.headlineSmall), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |           type == 'virtual' ? _cardVA(context) : const SizedBox(), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.symmetric(vertical: 16.0), | ||||||
|  |             child: Text('Purchase Details', style: textTheme.headlineSmall), | ||||||
|  |           ), | ||||||
|  |           Container( | ||||||
|  |             margin: const EdgeInsets.symmetric(vertical: 8.0), | ||||||
|  |             padding: const EdgeInsets.only(bottom: 16.0), | ||||||
|  |             decoration: BoxDecoration( | ||||||
|  |               color: Colors.white, | ||||||
|  |               border: Border.all(width: 1, color: ColorPalette.slate200), | ||||||
|  |               borderRadius: const BorderRadius.all(Radius.circular(12)), | ||||||
|  |             ), | ||||||
|  |             child: ExpansionTile( | ||||||
|  |               shape: ShapeBorder.lerp( | ||||||
|  |                   const StadiumBorder(side: BorderSide.none), | ||||||
|  |                   InputBorder.none, | ||||||
|  |                   0), | ||||||
|  |               title: Row( | ||||||
|  |                 children: [ | ||||||
|  |                   ImageView( | ||||||
|  |                     image: PathAssets.iconEducation, | ||||||
|  |                     width: SizeConfig.width * .08, | ||||||
|  |                   ), | ||||||
|  |                   const Padding( | ||||||
|  |                     padding: EdgeInsets.only(left: 8.0), | ||||||
|  |                     child: Text('Education'), | ||||||
|  |                   ), | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |               subtitle: Padding( | ||||||
|  |                 padding: const EdgeInsets.only(left: 40.0), | ||||||
|  |                 child: Text('3 Subscriptions', style: textTheme.bodyMedium), | ||||||
|  |               ), | ||||||
|  |               children: [ | ||||||
|  |                 _listProduct(context), | ||||||
|  |                 _listProduct(context), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           ...mySteps.map((e) { | ||||||
|  |             return _stepper( | ||||||
|  |               textTheme, | ||||||
|  |               description: '${e['desc']}', | ||||||
|  |               date: e['date'], | ||||||
|  |               time: e['time'], | ||||||
|  |               isActive: e['isActive'], | ||||||
|  |               isDone: e['isDone'], | ||||||
|  |               isLast: e['isLast'], | ||||||
|  |             ); | ||||||
|  |           }), | ||||||
|  |           Container( | ||||||
|  |               margin: const EdgeInsets.symmetric(vertical: 8.0), | ||||||
|  |               // padding: const EdgeInsets.only(bottom: 16.0), | ||||||
|  |               decoration: BoxDecoration( | ||||||
|  |                 color: Colors.white, | ||||||
|  |                 border: Border.all(width: 1, color: ColorPalette.slate200), | ||||||
|  |                 borderRadius: const BorderRadius.all(Radius.circular(12)), | ||||||
|  |               ), | ||||||
|  |               child: ExpansionTile( | ||||||
|  |                   shape: ShapeBorder.lerp( | ||||||
|  |                       const StadiumBorder(side: BorderSide.none), | ||||||
|  |                       InputBorder.none, | ||||||
|  |                       0), | ||||||
|  |                   title: Row( | ||||||
|  |                     children: [ | ||||||
|  |                       const Expanded( | ||||||
|  |                           child: Text('When Is My Purchase Complete?')), | ||||||
|  |                       ImageView( | ||||||
|  |                         image: PathAssets.imgExpandPurchase, | ||||||
|  |                         width: SizeConfig.width * .15, | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|  |                   ))), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Scaffold( | ||||||
|  |       body: SizedBox( | ||||||
|  |         child: Stack( | ||||||
|  |           children: [ | ||||||
|  |             const ImageView(image: PathAssets.imgDashboardAccount), | ||||||
|  |             Column( | ||||||
|  |               children: [ | ||||||
|  |                 SizedBox(height: SizeConfig.height * .05), | ||||||
|  |                 Padding( | ||||||
|  |                   padding: const EdgeInsets.all(16.0), | ||||||
|  |                   child: Row( | ||||||
|  |                     mainAxisAlignment: MainAxisAlignment.start, | ||||||
|  |                     children: [ | ||||||
|  |                       BackButtonView( | ||||||
|  |                         onPress: () => Navigator.pop(context), | ||||||
|  |                       ), | ||||||
|  |                       const Padding( | ||||||
|  |                         padding: EdgeInsets.symmetric(horizontal: 80.0), | ||||||
|  |                         child: Text( | ||||||
|  |                           'Subscribe Detail', | ||||||
|  |                           style: TextStyle( | ||||||
|  |                             fontSize: 18, | ||||||
|  |                             color: Colors.white, | ||||||
|  |                             fontWeight: FontWeight.bold, | ||||||
|  |                           ), | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 type == 'virtual' | ||||||
|  |                     ? const Padding( | ||||||
|  |                         padding: EdgeInsets.only(bottom: 8.0), | ||||||
|  |                         child: Text( | ||||||
|  |                           'Virtual Account', | ||||||
|  |                           style: TextStyle( | ||||||
|  |                             color: Colors.white, | ||||||
|  |                             fontSize: 16, | ||||||
|  |                           ), | ||||||
|  |                         ), | ||||||
|  |                       ) | ||||||
|  |                     : const SizedBox(), | ||||||
|  |                 Row( | ||||||
|  |                   mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |                   children: [ | ||||||
|  |                     ImageView( | ||||||
|  |                       image: PathAssets.imgProduct, | ||||||
|  |                       width: SizeConfig.width * .08, | ||||||
|  |                     ), | ||||||
|  |                     Padding( | ||||||
|  |                       padding: const EdgeInsets.only(left: 8.0), | ||||||
|  |                       child: Text( | ||||||
|  |                         type == 'virtual' ? 'ABC' : 'Shopping Pay', | ||||||
|  |                         style: const TextStyle( | ||||||
|  |                           fontWeight: FontWeight.bold, | ||||||
|  |                           color: Colors.white, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |                 const Padding( | ||||||
|  |                   padding: EdgeInsets.only(top: 8.0), | ||||||
|  |                   child: Row( | ||||||
|  |                     mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |                     children: [ | ||||||
|  |                       Text( | ||||||
|  |                         'No.Subscribe : ', | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           fontWeight: FontWeight.normal, | ||||||
|  |                           color: Colors.white, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       Text( | ||||||
|  |                         'PI9393084SDMI1', | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           fontWeight: FontWeight.bold, | ||||||
|  |                           color: Colors.white, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 Expanded( | ||||||
|  |                   child: Container( | ||||||
|  |                     color: Colors.transparent, | ||||||
|  |                     width: SizeConfig.width, | ||||||
|  |                     padding: const EdgeInsets.only(top: 16.0), | ||||||
|  |                     child: Container( | ||||||
|  |                         margin: const EdgeInsets.only(top: 32.0), | ||||||
|  |                         padding: const EdgeInsets.only(top: 32.0), | ||||||
|  |                         decoration: const BoxDecoration( | ||||||
|  |                           color: Colors.white, | ||||||
|  |                           borderRadius: BorderRadius.only( | ||||||
|  |                               topLeft: Radius.circular(24), | ||||||
|  |                               topRight: Radius.circular(24)), | ||||||
|  |                         ), | ||||||
|  |                         child: _cardContent(context)), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ) | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,15 +1,124 @@ | |||||||
| import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart'; | 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:cims_apps/core/utils/size_config.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/cancel_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/done_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/onprocess_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/waiting_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_toggle_tab/flutter_toggle_tab.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
| class TransactionView extends StatelessWidget { | class TransactionView extends StatelessWidget { | ||||||
|   const TransactionView({Key? key}) : super(key: key); |   const TransactionView({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Scaffold( |     List<Tab> textTabs = const [ | ||||||
|       appBar: |       Tab(text: 'Waiting'), | ||||||
|           CustomAppBar(height: SizeConfig.height * .1, title: 'Transaction'), |       Tab(text: 'On process'), | ||||||
|     ); |       Tab(text: 'Done'), | ||||||
|  |       Tab(text: 'Cancel'), | ||||||
|  |     ]; | ||||||
|  |     List<Widget> listTabBarView = const [ | ||||||
|  |       WaitingView(), | ||||||
|  |       OnProcessView(), | ||||||
|  |       DoneView(), | ||||||
|  |       CancelView(), | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     return ChangeNotifierProvider( | ||||||
|  |         create: (context) => TransactionViewModel(), | ||||||
|  |         builder: (context, child) { | ||||||
|  |           return Scaffold( | ||||||
|  |             backgroundColor: ColorPalette.primary, | ||||||
|  |             body: SizedBox( | ||||||
|  |               child: Stack( | ||||||
|  |                 children: [ | ||||||
|  |                   const ImageView(image: PathAssets.imgDashboardAccount), | ||||||
|  |                   Column( | ||||||
|  |                     children: [ | ||||||
|  |                       SizedBox( | ||||||
|  |                         height: SizeConfig.height * .05, | ||||||
|  |                       ), | ||||||
|  |                       const Center( | ||||||
|  |                         child: Text( | ||||||
|  |                           'Transaction', | ||||||
|  |                           style: TextStyle( | ||||||
|  |                               fontSize: 20, | ||||||
|  |                               fontWeight: FontWeight.w700, | ||||||
|  |                               color: Colors.white), | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       SizedBox( | ||||||
|  |                         height: SizeConfig.height * .04, | ||||||
|  |                       ), | ||||||
|  |                       Container( | ||||||
|  |                         margin: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|  |                         child: FlutterToggleTab( | ||||||
|  |                           height: SizeConfig.height * .065, | ||||||
|  |                           width: SizeConfig.width * .2, | ||||||
|  |                           marginSelected: const EdgeInsets.all(8.0), | ||||||
|  |                           isScroll: false, | ||||||
|  |                           selectedTextStyle: const TextStyle( | ||||||
|  |                             color: ColorPalette.primary, | ||||||
|  |                             fontWeight: FontWeight.w700, | ||||||
|  |                           ), | ||||||
|  |                           unSelectedTextStyle: const TextStyle( | ||||||
|  |                             color: ColorPalette.blackFont, | ||||||
|  |                             fontWeight: FontWeight.w700, | ||||||
|  |                           ), | ||||||
|  |                           unSelectedBackgroundColors: const [ | ||||||
|  |                             ColorPalette.blue50 | ||||||
|  |                           ], | ||||||
|  |                           selectedBackgroundColors: const [ColorPalette.white], | ||||||
|  |                           labels: const ['Subscribe', 'Reedem'], | ||||||
|  |                           selectedLabelIndex: (p0) {}, | ||||||
|  |                           selectedIndex: 0, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                       Expanded( | ||||||
|  |                           child: DefaultTabController( | ||||||
|  |                         length: textTabs.length, | ||||||
|  |                         child: Container( | ||||||
|  |                           color: Colors.transparent, | ||||||
|  |                           padding: const EdgeInsets.only(top: 32.0), | ||||||
|  |                           child: Container( | ||||||
|  |                             margin: const EdgeInsets.only(top: 24), | ||||||
|  |                             padding: const EdgeInsets.only(top: 16.0), | ||||||
|  |                             decoration: const BoxDecoration( | ||||||
|  |                               color: Colors.white, | ||||||
|  |                               borderRadius: BorderRadius.only( | ||||||
|  |                                   topLeft: Radius.circular(24), | ||||||
|  |                                   topRight: Radius.circular(24)), | ||||||
|  |                             ), | ||||||
|  |                             child: Column( | ||||||
|  |                               children: [ | ||||||
|  |                                 TabBar( | ||||||
|  |                                   tabs: textTabs, | ||||||
|  |                                   indicatorColor: Colors.blueAccent, | ||||||
|  |                                 ), | ||||||
|  |                                 Expanded( | ||||||
|  |                                     child: Padding( | ||||||
|  |                                   padding: const EdgeInsets.symmetric( | ||||||
|  |                                     horizontal: 16.0, | ||||||
|  |                                     vertical: 4.0, | ||||||
|  |                                   ), | ||||||
|  |                                   child: TabBarView(children: listTabBarView), | ||||||
|  |                                 )) | ||||||
|  |                               ], | ||||||
|  |                             ), | ||||||
|  |                           ), | ||||||
|  |                         ), | ||||||
|  |                       )), | ||||||
|  |                     ], | ||||||
|  |                   ) | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ); | ||||||
|  |         }); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								lib/features/transaction/view/waiting_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,49 @@ | |||||||
|  | import 'package:cims_apps/application/assets/path_assets.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart'; | ||||||
|  | import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart'; | ||||||
|  | import 'package:cims_apps/core/route/route.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/number_formatter.dart'; | ||||||
|  | import 'package:cims_apps/core/utils/string_utils.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart'; | ||||||
|  | import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
|  | class WaitingView extends StatelessWidget { | ||||||
|  |   const WaitingView({Key? key}) : super(key: key); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SingleChildScrollView( | ||||||
|  |       child: | ||||||
|  |           Consumer<TransactionViewModel>(builder: (context, provider, child) { | ||||||
|  |         return Column( | ||||||
|  |           children: [ | ||||||
|  |             provider.listWaitingTransaction.isNotEmpty | ||||||
|  |                 ? CardTransactionView( | ||||||
|  |                     onTap: () { | ||||||
|  |                       routePush(context, | ||||||
|  |                           page: const SubscribeDetailView( | ||||||
|  |                             type: 'normal', | ||||||
|  |                           )); | ||||||
|  |                     }, | ||||||
|  |                     iconPath: PathAssets.iconEducation, | ||||||
|  |                     type: 'Education', | ||||||
|  |                     amount: NumberFormatter.numberCurrency( | ||||||
|  |                       6000000, | ||||||
|  |                       'Rp ', | ||||||
|  |                       'id_ID', | ||||||
|  |                       decimalDigits: 0, | ||||||
|  |                     ), | ||||||
|  |                     timeTransaction: StringUtils.formatTime(DateTime.now()), | ||||||
|  |                     subs: '3 Subscription', | ||||||
|  |                     step: 'waiting') | ||||||
|  |                 : EmptyCardTransaction( | ||||||
|  |                     onPressedButton: () {}, | ||||||
|  |                   ), | ||||||
|  |           ], | ||||||
|  |         ); | ||||||
|  |       }), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
|  | class TransactionViewModel extends ChangeNotifier { | ||||||
|  |   List listWaitingTransaction = [1]; | ||||||
|  |   List listOnProcessTransaction = [1]; | ||||||
|  |   List listDoneTransaction = []; | ||||||
|  |   List listCancelTransaction = []; | ||||||
|  | } | ||||||
							
								
								
									
										114
									
								
								lib/main.dart
									
									
									
									
									
								
							
							
						
						| @@ -20,68 +20,66 @@ class MyApp extends StatelessWidget { | |||||||
|       title: 'CIMS', |       title: 'CIMS', | ||||||
|       debugShowCheckedModeBanner: false, |       debugShowCheckedModeBanner: false, | ||||||
|       theme: ThemeData( |       theme: ThemeData( | ||||||
|         appBarTheme: const AppBarTheme( |           appBarTheme: const AppBarTheme( | ||||||
|             centerTitle: true, |               centerTitle: true, | ||||||
|             backgroundColor: Colors.white, |               backgroundColor: Colors.white, | ||||||
|             elevation: 1, |               elevation: 1, | ||||||
|             foregroundColor: Colors.black, |               foregroundColor: Colors.black, | ||||||
|             titleTextStyle: TextStyle( |               titleTextStyle: TextStyle( | ||||||
|               fontSize: 20, |                 fontSize: 20, | ||||||
|               fontWeight: FontWeight.w700, |                 fontWeight: FontWeight.w700, | ||||||
|               fontFamily: 'Manrope', |                 fontFamily: 'Manrope', | ||||||
|  |                 color: ColorPalette.slate800, | ||||||
|  |               )), | ||||||
|  |           fontFamily: 'Manrope', | ||||||
|  |           scaffoldBackgroundColor: Colors.white, | ||||||
|  |           textTheme: const TextTheme( | ||||||
|  |             displaySmall: TextStyle( | ||||||
|  |               fontSize: 14, | ||||||
|  |               fontWeight: FontWeight.w500, | ||||||
|               color: ColorPalette.slate800, |               color: ColorPalette.slate800, | ||||||
|             )), |             ), | ||||||
|         fontFamily: 'Manrope', |             displayMedium: TextStyle( | ||||||
|         scaffoldBackgroundColor: Colors.white, |               fontSize: 16, | ||||||
|         textTheme: const TextTheme( |               fontWeight: FontWeight.w600, | ||||||
|           displaySmall: TextStyle( |               color: ColorPalette.slate800, | ||||||
|             fontSize: 14, |             ), | ||||||
|             fontWeight: FontWeight.w500, |             displayLarge: TextStyle( | ||||||
|             color: ColorPalette.slate800, |               fontSize: 16, | ||||||
|  |               fontWeight: FontWeight.bold, | ||||||
|  |               color: ColorPalette.slate800, | ||||||
|  |             ), | ||||||
|  |             bodyMedium: TextStyle( | ||||||
|  |               fontSize: 14, | ||||||
|  |               fontWeight: FontWeight.w600, | ||||||
|  |               color: ColorPalette.slate500, | ||||||
|  |             ), | ||||||
|  |             bodyLarge: TextStyle( | ||||||
|  |               fontSize: 16, | ||||||
|  |               fontWeight: FontWeight.bold, | ||||||
|  |               color: ColorPalette.slate500, | ||||||
|  |             ), | ||||||
|  |             headlineSmall: TextStyle( | ||||||
|  |               fontSize: 16, | ||||||
|  |               fontWeight: FontWeight.bold, | ||||||
|  |               color: ColorPalette.slate800, | ||||||
|  |             ), | ||||||
|  |             headlineLarge: TextStyle( | ||||||
|  |               fontSize: 28, | ||||||
|  |               fontWeight: FontWeight.bold, | ||||||
|  |               color: ColorPalette.slate800, | ||||||
|  |             ), | ||||||
|           ), |           ), | ||||||
|           displayMedium: TextStyle( |           colorScheme: const ColorScheme.light().copyWith( | ||||||
|             fontSize: 16, |             primary: const Color(0xff2563EB), | ||||||
|             fontWeight: FontWeight.w600, |             onPrimary: const Color(0xFFFF9130), | ||||||
|             color: ColorPalette.slate800, |             secondary: const Color(0xFFFECDA6), | ||||||
|  |             onBackground: const Color(0xFFA9A9A9), | ||||||
|           ), |           ), | ||||||
|           displayLarge: TextStyle( |           bottomSheetTheme: const BottomSheetThemeData( | ||||||
|             fontSize: 16, |               backgroundColor: Colors.white, surfaceTintColor: Colors.white) | ||||||
|             fontWeight: FontWeight.bold, |           // useMaterial3: true, | ||||||
|             color: ColorPalette.slate800, |  | ||||||
|           ), |           ), | ||||||
|           bodyMedium: TextStyle( |  | ||||||
|             fontSize: 14, |  | ||||||
|             fontWeight: FontWeight.w600, |  | ||||||
|             color: ColorPalette.slate500, |  | ||||||
|           ), |  | ||||||
|           bodyLarge: TextStyle( |  | ||||||
|             fontSize: 16, |  | ||||||
|             fontWeight: FontWeight.bold, |  | ||||||
|             color: ColorPalette.slate500, |  | ||||||
|           ), |  | ||||||
|           headlineSmall: TextStyle( |  | ||||||
|             fontSize: 16, |  | ||||||
|             fontWeight: FontWeight.bold, |  | ||||||
|             color: ColorPalette.slate800, |  | ||||||
|           ), |  | ||||||
|           headlineLarge: TextStyle( |  | ||||||
|             fontSize: 28, |  | ||||||
|             fontWeight: FontWeight.bold, |  | ||||||
|             color: ColorPalette.slate800, |  | ||||||
|           ), |  | ||||||
|         ), |  | ||||||
|         colorScheme: const ColorScheme.light().copyWith( |  | ||||||
|           primary: const Color(0xff2563EB), |  | ||||||
|           onPrimary: const Color(0xFFFF9130), |  | ||||||
|           secondary: const Color(0xFFFECDA6), |  | ||||||
|           onBackground: const Color(0xFFA9A9A9), |  | ||||||
|         ), |  | ||||||
|         bottomSheetTheme: BottomSheetThemeData( |  | ||||||
|           backgroundColor: Colors.white, |  | ||||||
|           surfaceTintColor: Colors.white |  | ||||||
|         ) |  | ||||||
|         // useMaterial3: true, |  | ||||||
|       ), |  | ||||||
|       initialRoute: initialRoute, |       initialRoute: initialRoute, | ||||||
|       onGenerateRoute: generateRoutes, |       onGenerateRoute: generateRoutes, | ||||||
|       navigatorObservers: [ |       navigatorObservers: [ | ||||||
|   | |||||||
| @@ -259,6 +259,14 @@ packages: | |||||||
|     description: flutter |     description: flutter | ||||||
|     source: sdk |     source: sdk | ||||||
|     version: "0.0.0" |     version: "0.0.0" | ||||||
|  |   flutter_toggle_tab: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: flutter_toggle_tab | ||||||
|  |       sha256: "90ad0d050f656df677998825f985637d010117a1793828cd7e6dadada4ecd2c5" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "1.4.1" | ||||||
|   flutter_web_plugins: |   flutter_web_plugins: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: flutter |     description: flutter | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ dependencies: | |||||||
|   shared_preferences: ^2.2.2 |   shared_preferences: ^2.2.2 | ||||||
|   calendar_date_picker2: ^0.5.3 |   calendar_date_picker2: ^0.5.3 | ||||||
|   google_sign_in: ^6.2.1 |   google_sign_in: ^6.2.1 | ||||||
|  |   flutter_toggle_tab: ^1.4.1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||