Compare commits
	
		
			7 Commits
		
	
	
		
			main
			...
			d82d427bcc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d82d427bcc | |||
| e63e5588fb | |||
| f407eca735 | |||
| ff1886cec1 | |||
| 1616f22925 | |||
| 0b754bf939 | |||
| 0e7ad81345 | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-portofolio-bonds.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-portofolio-moneymarket.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-portofolio-shares.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-portofolio-sharia.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-shield.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-articles.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 154 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-carousel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 636 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-dashboard-account.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 MiB | 
| @@ -10,6 +10,11 @@ class PathAssets { | ||||
|   static const String iconGoogle = 'assets/icons/icon-google.png'; | ||||
|   static const String icon1 = 'assets/icons/icon-1.png'; | ||||
|   static const String iconConnect = 'assets/icons/icon-connect.png'; | ||||
|   static const String iconPortofolioBonds = 'assets/icons/icon-portofolio-bonds.png'; | ||||
|   static const String iconPortofolioShares = 'assets/icons/icon-portofolio-shares.png'; | ||||
|   static const String iconPortofolioSharia = 'assets/icons/icon-portofolio-sharia.png'; | ||||
|   static const String iconPortofolioMoneyMarket = 'assets/icons/icon-portofolio-moneymarket.png'; | ||||
|   static const String iconShield = 'assets/icons/icon-shield.png'; | ||||
|  | ||||
|   /// IMAGE | ||||
|   static const String imgSplashLogo = 'assets/images/splash-logo.png'; | ||||
| @@ -22,4 +27,7 @@ class PathAssets { | ||||
|   static const String imgKtpCropped = 'assets/images/img-ktp-cropped.png'; | ||||
|   static const String imgKtpClear = 'assets/images/img-ktp-clear.png'; | ||||
|   static const String imgKtpBlur = 'assets/images/img-ktp-blur.png'; | ||||
|   static const String imgDashboardAccount = 'assets/images/img-dashboard-account.png'; | ||||
|   static const String imgCarousel = 'assets/images/img-carousel.png'; | ||||
|   static const String imgArticles = 'assets/images/img-articles.png'; | ||||
| } | ||||
|   | ||||
							
								
								
									
										23
									
								
								lib/application/component/button/button_back.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,23 @@ | ||||
| import 'package:cims_apps/core/utils/size_config.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class ButtonBack extends StatelessWidget { | ||||
|   const ButtonBack({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return SizedBox( | ||||
|       width: SizeConfig.width * 0.1, | ||||
|       child: IconButton( | ||||
|           style: IconButton.styleFrom( | ||||
|               backgroundColor: Colors.white, | ||||
|               shape: const CircleBorder() | ||||
|           ), | ||||
|           onPressed: () { | ||||
|             Navigator.pop(context); | ||||
|           }, | ||||
|           icon: const Icon(Icons.arrow_back) | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										176
									
								
								lib/application/component/select_form/select_form_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,176 @@ | ||||
| import 'package:cims_apps/application/component/button/button_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:flutter/material.dart'; | ||||
|  | ||||
| class ItemSelectForm { | ||||
|   final String key; | ||||
|   final String text; | ||||
|   final String? description; | ||||
|   final bool isOther; | ||||
|   final String image; | ||||
|  | ||||
|   ItemSelectForm( | ||||
|     this.key, | ||||
|     this.text, { | ||||
|     this.isOther = false, | ||||
|     this.image = "", | ||||
|     this.description, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| class SelectFormView extends StatelessWidget { | ||||
|   final String name; | ||||
|   final String? hintText; | ||||
|   final TextStyle? hintTextStyle; | ||||
|   final TextEditingController? ctrl; | ||||
|   final Widget? bottomSheetTitle; | ||||
|   final List<ItemSelectForm> listItem; | ||||
|   final ValueChanged<String> onSelect; | ||||
|   final FormFieldValidator<String>? validator; | ||||
|   final _borderRadius = const Radius.circular(24); | ||||
|   final bool? enabled; | ||||
|   const SelectFormView( | ||||
|       {Key? key, | ||||
|       required this.name, | ||||
|       this.hintText, | ||||
|       this.hintTextStyle, | ||||
|       this.ctrl, | ||||
|       this.bottomSheetTitle, | ||||
|       required this.listItem, | ||||
|       required this.onSelect, | ||||
|       this.validator, | ||||
|       this.enabled}) | ||||
|       : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     bottomSheet() { | ||||
|       showModalBottomSheet<void>( | ||||
|         context: context, | ||||
|         shape: RoundedRectangleBorder( | ||||
|           borderRadius: BorderRadius.only( | ||||
|             topLeft: _borderRadius, | ||||
|             topRight: _borderRadius, | ||||
|           ), | ||||
|         ), | ||||
|         builder: (BuildContext context) { | ||||
|           ItemSelectForm? selectedForm; | ||||
|           String? selectedKey; | ||||
|           if (listItem.isNotEmpty) { | ||||
|             var res = listItem.where((element) => element.key == selectedKey); | ||||
|             if (res.isNotEmpty) { | ||||
|               selectedForm = res.first; | ||||
|             } | ||||
|           } | ||||
|           return StatefulBuilder(builder: ( | ||||
|             BuildContext context, | ||||
|             StateSetter stateSetter, | ||||
|           ) { | ||||
|             return Container( | ||||
|               height: SizeConfig.height * .45, | ||||
|               padding: const EdgeInsets.all(16), | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                 children: [ | ||||
|                   bottomSheetTitle ?? Container(), | ||||
|                   // const SizedBox(height: 16), | ||||
|                   Expanded( | ||||
|                     child: SingleChildScrollView( | ||||
|                       scrollDirection: Axis.vertical, | ||||
|                       child: Column( | ||||
|                         children: [ | ||||
|                           ...listItem.map( | ||||
|                             (e) => Card( | ||||
|                               elevation: 0, | ||||
|                               color: Colors.transparent, | ||||
|                               shape: const RoundedRectangleBorder( | ||||
|                                 side: BorderSide( | ||||
|                                   color: ColorPalette.greyBorder, | ||||
|                                 ), | ||||
|                                 borderRadius: | ||||
|                                     BorderRadius.all(Radius.circular(12)), | ||||
|                               ), | ||||
|                               child: ListTile( | ||||
|                                 title: Text( | ||||
|                                   e.text, | ||||
|                                   style: const TextStyle( | ||||
|                                     fontSize: 14, | ||||
|                                   ), | ||||
|                                 ), | ||||
|                                 subtitle: e.description != null | ||||
|                                     ? Text( | ||||
|                                         e.description!, | ||||
|                                         maxLines: 2, | ||||
|                                         overflow: TextOverflow.ellipsis, | ||||
|                                       ) | ||||
|                                     : null, | ||||
|                                 // trailing: const Icon( | ||||
|                                 //   Icons.check_circle, | ||||
|                                 //   color: ColorPalette.primary, | ||||
|                                 // ), | ||||
|                                 trailing: Radio( | ||||
|                                   focusColor: ColorPalette.primary, | ||||
|                                   activeColor: ColorPalette.primary, | ||||
|                                   visualDensity: const VisualDensity( | ||||
|                                     horizontal: VisualDensity.minimumDensity, | ||||
|                                     vertical: VisualDensity.minimumDensity, | ||||
|                                   ), | ||||
|                                   materialTapTargetSize: | ||||
|                                       MaterialTapTargetSize.shrinkWrap, | ||||
|                                   value: e.key, | ||||
|                                   groupValue: selectedKey, | ||||
|                                   onChanged: (value) { | ||||
|                                     // selectedForm = | ||||
|                                     //     ItemSelectForm(e.key, e.text); | ||||
|                                     // stateSetter(() { | ||||
|                                     //   selectedKey = selectedForm!.key; | ||||
|                                     // }); | ||||
|                                   }, | ||||
|                                 ), | ||||
|                                 onTap: () { | ||||
|                                   ctrl?.text = e.text; | ||||
|                                   onSelect(e.key); | ||||
|                                   Navigator.of(context).pop(); | ||||
|                                 }, | ||||
|                               ), | ||||
|                             ), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                   ButtonView( | ||||
|                     name: 'Select', | ||||
|                     marginVertical: 4.0, | ||||
|                     onPressed: () { | ||||
|                       // print('object $') | ||||
|                     }, | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|             ); | ||||
|           }); | ||||
|         }, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return TextFormView( | ||||
|       name: name, | ||||
|       readOnly: true, | ||||
|       enabled: enabled ?? true, | ||||
|       onTap: () { | ||||
|         if (listItem.isNotEmpty) bottomSheet(); | ||||
|       }, | ||||
|       validator: validator, | ||||
|       hintText: hintText, | ||||
|       hintTextStyle: hintTextStyle, | ||||
|       ctrl: ctrl, | ||||
|       suffixIcon: Icon( | ||||
|         Icons.keyboard_arrow_down, | ||||
|         size: SizeConfig.width * .07, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -155,7 +155,7 @@ class TextFormView extends StatelessWidget { | ||||
|             hintStyle: hintTextStyle ?? | ||||
|                 const TextStyle( | ||||
|                   fontSize: 14, | ||||
|                   color: Colors.grey, | ||||
|                   color: ColorPalette.greyFont, | ||||
|                   fontWeight: FontWeight.normal, | ||||
|                 ), | ||||
|             isDense: true, | ||||
| @@ -167,19 +167,19 @@ class TextFormView extends StatelessWidget { | ||||
|             disabledBorder: OutlineInputBorder( | ||||
|               borderRadius: _borderRadius, | ||||
|               borderSide: BorderSide( | ||||
|                 color: disabledborderColor ?? ColorPalette.greyFont, | ||||
|                 color: disabledborderColor ?? ColorPalette.greyBorder, | ||||
|               ), | ||||
|             ), | ||||
|             enabledBorder: OutlineInputBorder( | ||||
|               borderRadius: _borderRadius, | ||||
|               borderSide: BorderSide( | ||||
|                 color: enabledborderColor ?? ColorPalette.greyBase, | ||||
|                 color: enabledborderColor ?? ColorPalette.greyBorder, | ||||
|               ), | ||||
|             ), | ||||
|             focusedBorder: OutlineInputBorder( | ||||
|               borderRadius: _borderRadius, | ||||
|               borderSide: BorderSide( | ||||
|                 color: focusedBorderColor ?? ColorPalette.greyBase, | ||||
|                 color: focusedBorderColor ?? ColorPalette.greyBorder, | ||||
|               ), | ||||
|             ), | ||||
|             border: OutlineInputBorder(borderRadius: _borderRadius), | ||||
|   | ||||
							
								
								
									
										26
									
								
								lib/application/component/text_title/text_title.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,26 @@ | ||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
|  | ||||
| class TextTitle extends StatelessWidget { | ||||
|   final String title; | ||||
|   final Color? color; | ||||
|   final double? fontSize; | ||||
|   const TextTitle({ | ||||
|     Key? key, | ||||
|     required this.title, | ||||
|     this.color, | ||||
|     this.fontSize, | ||||
|   }) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Text( | ||||
|       title, | ||||
|       style: TextStyle( | ||||
|         fontSize: fontSize ?? 20, | ||||
|         fontWeight: FontWeight.w700, | ||||
|         color: color ?? ColorPalette.slate800, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -73,5 +73,34 @@ class ColorPalette { | ||||
|   static const Color chathamsBlue = Color(0xFF285BB9); | ||||
|   static const Color background = Color(0xFFDADADA); | ||||
|   static const Color backgroundBlueLight = Color(0xFFEBF3FD); | ||||
|   static const Color blue200 = Color(0xFFBFDBFE); | ||||
|   static const Color slate50 = Color(0xFFF8FAFC); | ||||
|   static const Color slate200 = Color(0xFFE2E8F0); | ||||
|   static const Color slate400 = Color(0xFF94A3B8); | ||||
|   static const Color slate500 = Color(0xFF64748B); | ||||
|   static const Color slate800 = Color(0xFF1E293B); | ||||
|   static const Color purple100 = Color(0xFFEDE9FE); | ||||
|   static const Color purple500 = Color(0xFF8B5CF6); | ||||
|   static const Color orange100 = Color(0xFFFFEDD5); | ||||
|   static const Color orange500 = Color(0xFFF97316); | ||||
|   static const Color cyan100 = Color(0xFFCFFAFE); | ||||
|   static const Color cyan500 = Color(0xFF06B6D4); | ||||
|   static const Color green100 = Color(0xFFDCFCE7); | ||||
|   static const Color green400 = Color(0xFF4ADE80); | ||||
|   static const Color green500 = Color(0xFF16A34A); | ||||
|  | ||||
|  | ||||
|   static const Map<String, Color> investTypeColor = { | ||||
|     'Money Market': purple500, | ||||
|     'Shares': orange500, | ||||
|     'Sharia': green500, | ||||
|     'Bonds': cyan500 | ||||
|   }; | ||||
|  | ||||
|   static const Map<String, Color> investTypeBgColor = { | ||||
|     'Money Market': purple100, | ||||
|     'Shares': orange100, | ||||
|     'Sharia': green100, | ||||
|     'Bonds': cyan100 | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ 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/core/route/route.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart'; | ||||
| import 'package:cims_apps/features/bottom_navigation_view.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| @@ -42,7 +41,7 @@ class RegistrationView extends StatelessWidget { | ||||
|                     text: 'Already have an account? ', | ||||
|                     style: TextStyle( | ||||
|                       color: Colors.black, | ||||
|                       decoration: TextDecoration.underline, | ||||
|                       decoration: TextDecoration.none, | ||||
|                     ), | ||||
|                   ), | ||||
|                   TextSpan( | ||||
|   | ||||
| @@ -0,0 +1,91 @@ | ||||
| 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_caption/text_caption.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 InitialTakePhoto extends StatelessWidget { | ||||
|   const InitialTakePhoto({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     List listImg = [ | ||||
|       {'urlImg': PathAssets.imgKtpBlur, 'tag': 'Blurry Photo'}, | ||||
|       {'urlImg': PathAssets.imgKtpLight, 'tag': 'Light Reflection'}, | ||||
|       {'urlImg': PathAssets.imgKtpCropped, 'tag': 'Cropped Photo'}, | ||||
|       {'urlImg': PathAssets.imgKtpClear, 'tag': 'Clear Photo'}, | ||||
|     ]; | ||||
|     return SizedBox( | ||||
|       height: SizeConfig.height * .75, | ||||
|       child: Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|         children: [ | ||||
|           const TextCaption( | ||||
|             title: 'Take a photo your ID card', | ||||
|             subtitle: | ||||
|                 'Make sure your photo is clearly legible for identity verification purposes', | ||||
|           ), | ||||
|           SizedBox( | ||||
|             width: SizeConfig.height, | ||||
|             child: Wrap( | ||||
|               alignment: WrapAlignment.spaceBetween, | ||||
|               spacing: 10, | ||||
|               runSpacing: 10, | ||||
|               children: List.generate(listImg.length, (index) { | ||||
|                 final urlList = listImg[index]['urlImg']; | ||||
|                 final tag = listImg[index]['tag']; | ||||
|                 return Column( | ||||
|                   children: [ | ||||
|                     ImageView( | ||||
|                       image: urlList, | ||||
|                       width: SizeConfig.width * .42, | ||||
|                     ), | ||||
|                     const SizedBox( | ||||
|                       height: 8, | ||||
|                     ), | ||||
|                     Text( | ||||
|                       tag, | ||||
|                       style: const TextStyle( | ||||
|                           color: ColorPalette.slate800, | ||||
|                           fontWeight: FontWeight.w600), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ); | ||||
|               }), | ||||
|             ), | ||||
|           ), | ||||
|           // const Spacer(), | ||||
|           const Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               ImageView( | ||||
|                 image: PathAssets.iconShield, | ||||
|                 width: 20, | ||||
|                 height: 22, | ||||
|               ), | ||||
|               SizedBox( | ||||
|                 width: 8, | ||||
|               ), | ||||
|               Expanded( | ||||
|                 child: Text( | ||||
|                   'In accordance with OJK regulations, an ID card is required to purchase mutual funds.', | ||||
|                   style: TextStyle( | ||||
|                     fontWeight: FontWeight.w600, | ||||
|                     color: ColorPalette.primary, | ||||
|                   ), | ||||
|                 ), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|           ButtonView( | ||||
|             name: 'Take a Photo', | ||||
|             marginVertical: 16.0, | ||||
|             onPressed: () {}, | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -1,9 +1,12 @@ | ||||
| import 'package:cims_apps/application/component/button/button_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/view/submission_data/initial_take_photo.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/view/submission_data/submit_email.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/view/submission_data/submit_personal_data.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
|  | ||||
| class SubmissionParent extends StatefulWidget { | ||||
|   static const routeName = '/SubmissionParent'; | ||||
| @@ -14,29 +17,16 @@ class SubmissionParent extends StatefulWidget { | ||||
| } | ||||
|  | ||||
| class _SubmissionParentState extends State<SubmissionParent> { | ||||
|   int _currentStep = 1; | ||||
|   final int _stepAmount = 9; | ||||
|   Widget _stepItem({bool isCurrentStep = false, bool isDone = false}) { | ||||
|     return GestureDetector( | ||||
|       onTap: () { | ||||
|         setState(() { | ||||
|           if (_currentStep > 1) { | ||||
|             _currentStep--; | ||||
|           } else if (_currentStep == 1) { | ||||
|             _currentStep++; | ||||
|           } | ||||
|         }); | ||||
|       }, | ||||
|       child: Container( | ||||
|         margin: const EdgeInsets.only(right: 4.0, left: 4.0), | ||||
|         height: 6, | ||||
|         width: SizeConfig.width * .08, | ||||
|         decoration: BoxDecoration( | ||||
|           color: isCurrentStep || isDone | ||||
|               ? ColorPalette.primary | ||||
|               : ColorPalette.greyBorderNeutrals, | ||||
|           borderRadius: BorderRadius.circular(50), | ||||
|         ), | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.only(right: 4.0, left: 4.0), | ||||
|       height: 6, | ||||
|       width: SizeConfig.width * .08, | ||||
|       decoration: BoxDecoration( | ||||
|         color: isCurrentStep || isDone | ||||
|             ? ColorPalette.primary | ||||
|             : ColorPalette.greyBorderNeutrals, | ||||
|         borderRadius: BorderRadius.circular(50), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| @@ -48,9 +38,7 @@ class _SubmissionParentState extends State<SubmissionParent> { | ||||
|       case 2: | ||||
|         return const SubmitEmail(); | ||||
|       case 3: | ||||
|         return Container( | ||||
|           child: Text("Step 3"), | ||||
|         ); | ||||
|         return const InitialTakePhoto(); | ||||
|       case 4: | ||||
|         return Container( | ||||
|           child: Text("Step 4"), | ||||
| @@ -80,48 +68,58 @@ class _SubmissionParentState extends State<SubmissionParent> { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       appBar: AppBar( | ||||
|         title: const Text('Registration'), | ||||
|       ), | ||||
|       body: Stack( | ||||
|         children: [ | ||||
|           Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
|             children: [ | ||||
|               Padding( | ||||
|                 padding: const EdgeInsets.symmetric( | ||||
|                     horizontal: 16.0, vertical: 16.0), | ||||
|                 child: Row( | ||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                   children: List.generate( | ||||
|                     _stepAmount, | ||||
|                     (index) => _stepItem( | ||||
|                       isCurrentStep: _currentStep == index + 1, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|               Container( | ||||
|                 padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||
|                 child: _content(_currentStep), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|           Align( | ||||
|             alignment: Alignment.bottomCenter, | ||||
|             child: ButtonView( | ||||
|               name: 'Next', | ||||
|               marginVertical: 16.0, | ||||
|               onPressed: () { | ||||
|                 setState(() { | ||||
|                   _currentStep++; | ||||
|                 }); | ||||
|               }, | ||||
|     return ChangeNotifierProvider( | ||||
|         create: (context) => SubmissionDataViewModel(), | ||||
|         builder: (context, child) { | ||||
|           return Scaffold( | ||||
|             appBar: AppBar( | ||||
|               title: const Text('Registration'), | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|             body: Stack( | ||||
|               children: [ | ||||
|                 Consumer<SubmissionDataViewModel>( | ||||
|                     builder: (context, provider, child) { | ||||
|                   return Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                     children: [ | ||||
|                       Padding( | ||||
|                         padding: const EdgeInsets.symmetric( | ||||
|                             horizontal: 16.0, vertical: 16.0), | ||||
|                         child: Row( | ||||
|                           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                           children: List.generate( | ||||
|                             provider.stepAmount, | ||||
|                             (index) => _stepItem( | ||||
|                               isCurrentStep: provider.currentStep == index + 1, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                       Expanded( | ||||
|                         child: Container( | ||||
|                           padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||||
|                           child: _content(provider.currentStep), | ||||
|                         ), | ||||
|                       ), | ||||
|                       provider.currentStep == 3 | ||||
|                           ? const SizedBox() | ||||
|                           : Align( | ||||
|                               alignment: Alignment.bottomCenter, | ||||
|                               child: ButtonView( | ||||
|                                 name: 'Next', | ||||
|                                 marginVertical: 16.0, | ||||
|                                 onPressed: () { | ||||
|                                   provider.nextSubmission(context); | ||||
|                                 }, | ||||
|                               ), | ||||
|                             ) | ||||
|                     ], | ||||
|                   ); | ||||
|                 }), | ||||
|               ], | ||||
|             ), | ||||
|           ); | ||||
|         }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,21 +1,81 @@ | ||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | ||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | ||||
| import 'package:cims_apps/application/component/text_caption/text_caption.dart'; | ||||
| import 'package:cims_apps/application/component/text_form/text_form_view.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
|  | ||||
| class SubmitEmail extends StatelessWidget { | ||||
|   const SubmitEmail({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   Widget _emailVerify() { | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         const TextCaption(title: 'Enter your e-mail'), | ||||
|         TextFormView( | ||||
|           name: 'E-mail Address', | ||||
|           hintText: 'Input e-mail address', | ||||
|         const ImageView(image: PathAssets.imgEmail), | ||||
|         Align( | ||||
|           alignment: Alignment.center, | ||||
|           child: RichText( | ||||
|             textAlign: TextAlign.center, | ||||
|             text: TextSpan(children: [ | ||||
|               const TextSpan( | ||||
|                 text: | ||||
|                     'We have sent a verification link to your e-mail. \nPlease check your email for ', | ||||
|                 style: TextStyle( | ||||
|                   color: Colors.black, | ||||
|                   decoration: TextDecoration.none, | ||||
|                 ), | ||||
|               ), | ||||
|               TextSpan( | ||||
|                 recognizer: TapGestureRecognizer() | ||||
|                   ..onTap = () { | ||||
|                     print('object'); | ||||
|                   }, | ||||
|                 text: 'verification', | ||||
|                 style: const TextStyle( | ||||
|                   color: Colors.blue, | ||||
|                 ), | ||||
|               ), | ||||
|               const TextSpan( | ||||
|                 text: ' to \ncontinue registration.', | ||||
|                 style: TextStyle( | ||||
|                   color: Colors.black, | ||||
|                   decoration: TextDecoration.none, | ||||
|                 ), | ||||
|               ), | ||||
|             ]), | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return ChangeNotifierProvider( | ||||
|         create: (context) => SubmissionDataViewModel(), | ||||
|         builder: (context, child) { | ||||
|           return Consumer<SubmissionDataViewModel>( | ||||
|               builder: (context, provider, child) { | ||||
|             return Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 !provider.isEmailVerify | ||||
|                     ? const TextCaption(title: 'Enter your e-mail') | ||||
|                     : const TextCaption(title: 'Check your e-mail '), | ||||
|                 !provider.isEmailVerify | ||||
|                     ? TextFormView( | ||||
|                         name: 'E-mail Address', | ||||
|                         hintText: 'Input e-mail address', | ||||
|                         onTap: () { | ||||
|                           provider.submitEmail(); | ||||
|                         }, | ||||
|                       ) | ||||
|                     : _emailVerify(), | ||||
|               ], | ||||
|             ); | ||||
|           }); | ||||
|         }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,16 +1,56 @@ | ||||
| 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/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
|  | ||||
| class SubmitPersonalData extends StatelessWidget { | ||||
|   const SubmitPersonalData({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         TextCaption(title: 'Your personal details'), | ||||
|       ], | ||||
|     ); | ||||
|     List<ItemSelectForm> listForm = [ | ||||
|       ItemSelectForm('key1', 'text'), | ||||
|       ItemSelectForm('key2', 'text'), | ||||
|       ItemSelectForm('key3', 'text'), | ||||
|       ItemSelectForm('key4', 'text'), | ||||
|       ItemSelectForm('key5', 'text'), | ||||
|     ]; | ||||
|     return ChangeNotifierProvider( | ||||
|         create: (context) => SubmissionDataViewModel(), | ||||
|         builder: (context, child) { | ||||
|           return Consumer<SubmissionDataViewModel>( | ||||
|               builder: (context, provider, child) { | ||||
|             return SingleChildScrollView( | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                 // mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                 children: [ | ||||
|                   const TextCaption(title: 'Your personal details'), | ||||
|                   SelectFormView( | ||||
|                     name: 'Occupation', | ||||
|                     hintText: 'Select occupation ', | ||||
|                     bottomSheetTitle: Row( | ||||
|                       mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                       children: [ | ||||
|                         const Text('Occupation'), | ||||
|                         IconButton( | ||||
|                             onPressed: () => Navigator.pop(context), | ||||
|                             icon: const Icon( | ||||
|                               Icons.clear, | ||||
|                               size: 20, | ||||
|                               color: ColorPalette.greyBase, | ||||
|                             )), | ||||
|                       ], | ||||
|                     ), | ||||
|                     listItem: listForm, | ||||
|                     onSelect: (value) {}, | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ); | ||||
|           }); | ||||
|         }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class SubmissionDataViewModel extends ChangeNotifier { | ||||
|   int currentStep = 1; | ||||
|   int stepAmount = 9; | ||||
|   bool _isEmailVerify = false; | ||||
|   bool get isEmailVerify => _isEmailVerify; | ||||
|  | ||||
|   submitEmail() { | ||||
|     _isEmailVerify = !_isEmailVerify; | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   onWillPopSubmission(BuildContext context) { | ||||
|     if (currentStep != 1) { | ||||
|       currentStep--; | ||||
|       notifyListeners(); | ||||
|     } else { | ||||
|       Navigator.of(context).pop(true); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   nextSubmission(BuildContext context) { | ||||
|     if (currentStep < stepAmount) { | ||||
|       currentStep++; | ||||
|     } else { | ||||
|       //ToDo : Go To next step after completing the submission | ||||
|     } | ||||
|     notifyListeners(); | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,6 @@ | ||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart'; | ||||
| import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class BottomNavigationView extends StatefulWidget { | ||||
| @@ -15,15 +17,12 @@ class _BottomNavigationViewState extends State<BottomNavigationView> { | ||||
|   Widget build(BuildContext context) { | ||||
|     ///TODO: masukan pagenya dilistWidget ini | ||||
|     List<Widget> listWidget = [ | ||||
|       Container( | ||||
|         color: Colors.amberAccent, | ||||
|       ), | ||||
|       HomeView(), | ||||
|       Container( | ||||
|         color: Colors.redAccent, | ||||
|       ), | ||||
|       Container(), | ||||
|       Container(), | ||||
|       Container(), | ||||
|       PortofolioView(), | ||||
|       Container(), | ||||
|     ]; | ||||
|  | ||||
| @@ -60,6 +59,7 @@ class _BottomNavigationViewState extends State<BottomNavigationView> { | ||||
|         }, | ||||
|         currentIndex: _selectedIndex, | ||||
|         items: listNavigation, | ||||
|         type: BottomNavigationBarType.fixed, | ||||
|         showUnselectedLabels: true, | ||||
|         selectedItemColor: ColorPalette.primary, | ||||
|         unselectedItemColor: Colors.black, | ||||
|   | ||||
| @@ -0,0 +1,529 @@ | ||||
| import 'package:carousel_slider/carousel_slider.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/text_title/text_title.dart'; | ||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/core/route/route.dart'; | ||||
| import 'package:cims_apps/core/utils/size_config.dart'; | ||||
| import 'package:cims_apps/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class InvestType { | ||||
|   String name; | ||||
|   String iconImage; | ||||
|  | ||||
|   InvestType(this.name, this.iconImage); | ||||
| } | ||||
|  | ||||
| class StepVerification { | ||||
|   int currentStep; | ||||
|   List<String> nameStep; | ||||
|  | ||||
|   StepVerification(this.currentStep, this.nameStep); | ||||
| } | ||||
|  | ||||
| class Article { | ||||
|   String image; | ||||
|   String title; | ||||
|   String type; | ||||
|  | ||||
|   Article(this.type, this.title, this.image); | ||||
| } | ||||
|  | ||||
| class HomeView extends StatefulWidget { | ||||
|   const HomeView({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<HomeView> createState() => _HomeViewState(); | ||||
| } | ||||
|  | ||||
| class _HomeViewState extends State<HomeView> { | ||||
|   bool seePortofolioValue = false; | ||||
|  | ||||
|   List<InvestType> listPortofolioType = [ | ||||
|     InvestType('Money Market', PathAssets.iconPortofolioMoneyMarket), | ||||
|     InvestType('Shares', PathAssets.iconPortofolioShares), | ||||
|     InvestType('Bonds', PathAssets.iconPortofolioBonds), | ||||
|     InvestType('Sharia', PathAssets.iconPortofolioSharia) | ||||
|   ]; | ||||
|  | ||||
|   StepVerification listStepVerification = StepVerification(1, [ | ||||
|     'Registration', 'Verification', 'Complete' | ||||
|   ]); | ||||
|  | ||||
|   List<Article> listArticle = [ | ||||
|     Article('Education', 'Menggali Potensi Pasar: Analisis Sebelum Memulai Investasi', PathAssets.imgArticles), | ||||
|     Article('News', 'Tren Investasi 2024: Peluang dan Risiko yang Perlu Diketahui', PathAssets.imgArticles), | ||||
|     Article('Education', 'Investasi Berkelanjutan: Mengenal Portofolio Hijau untuk Masa Depan', PathAssets.imgArticles), | ||||
|   ]; | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       backgroundColor: const Color(0xffF8FAFC), | ||||
|       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.only(left: 24, right: 16), | ||||
|                   child: Row( | ||||
|                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                     children: [ | ||||
|                       const Text( | ||||
|                         'Home', | ||||
|                         style: TextStyle( | ||||
|                             color: Colors.white, | ||||
|                             fontSize: 20, | ||||
|                             fontWeight: FontWeight.w700 | ||||
|                         ), | ||||
|                       ), | ||||
|                       ElevatedButton( | ||||
|                           onPressed: () { | ||||
|  | ||||
|                           }, | ||||
|                           style: ElevatedButton.styleFrom( | ||||
|                               padding: const EdgeInsets.all(0), | ||||
|                               backgroundColor: Colors.white, | ||||
|                               foregroundColor: const Color(0xff2563EB), | ||||
|                               elevation: 0, | ||||
|                               shape: const CircleBorder() | ||||
|                           ), | ||||
|                           child: const Icon(Icons.notifications_outlined) | ||||
|                       ) | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 32, | ||||
|                 ), | ||||
|                 Padding( | ||||
|                   padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|                   child: portofolioValue(), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 24, | ||||
|                 ), | ||||
|                 cardInvestType(), | ||||
|                 const SizedBox( | ||||
|                   height: 32, | ||||
|                 ), | ||||
|                 Expanded( | ||||
|                   child: ListView( | ||||
|                     padding: const EdgeInsets.all(0), | ||||
|                     children: [ | ||||
|                       cardVerification(), | ||||
|                       const SizedBox( | ||||
|                         height: 24, | ||||
|                       ), | ||||
|                       infoAndPromo(), | ||||
|                       const SizedBox( | ||||
|                         height: 24, | ||||
|                       ), | ||||
|                       articles(), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget portofolioValue() { | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         Row( | ||||
|           children: [ | ||||
|             const Text('Portofolio Value', style: TextStyle(color: Colors.white)), | ||||
|             const SizedBox( | ||||
|               width: 12, | ||||
|             ), | ||||
|             GestureDetector( | ||||
|                 onTap: () { | ||||
|                   setState(() { | ||||
|                     seePortofolioValue = !seePortofolioValue; | ||||
|                   }); | ||||
|                 }, | ||||
|                 child: const Icon(Icons.visibility_outlined, color: Color(0xff93C5FD)) | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|         const SizedBox( | ||||
|           height: 4, | ||||
|         ), | ||||
|         Row( | ||||
|           children: [ | ||||
|             AnimatedCrossFade( | ||||
|               duration: const Duration(milliseconds: 300), | ||||
|               alignment: Alignment.center, | ||||
|               crossFadeState: seePortofolioValue ? CrossFadeState.showSecond : CrossFadeState.showFirst, | ||||
|               firstChild: RichText( | ||||
|                   text: const TextSpan( | ||||
|                       text: 'Rp ', | ||||
|                       style: TextStyle(fontSize: 32, color: Color(0xff93C5FD), fontFamily: 'Manrope',), | ||||
|                       children: [ | ||||
|                         TextSpan( | ||||
|                           text: '22.500.000', | ||||
|                           style: TextStyle( | ||||
|                               fontSize: 32, | ||||
|                               fontWeight: FontWeight.bold, | ||||
|                               color: Colors.white, | ||||
|                               fontFamily: 'Manrope', | ||||
|                           ), | ||||
|                         ) | ||||
|                       ] | ||||
|                   ) | ||||
|               ), | ||||
|               secondChild: Padding( | ||||
|                 padding: const EdgeInsets.symmetric(vertical: 16), | ||||
|                 child: Wrap( | ||||
|                   spacing: 7, | ||||
|                   children: [ | ||||
|                     for (int i = 0; i < 6; i++) | ||||
|                       Container( | ||||
|                         width: 12, | ||||
|                         height: 12, | ||||
|                         decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle), | ||||
|                       ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ], | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget cardInvestType() { | ||||
|     return Container( | ||||
|       padding: const EdgeInsets.all(16), | ||||
|       decoration: BoxDecoration( | ||||
|           color: Colors.white, | ||||
|           borderRadius: BorderRadius.circular(12), | ||||
|           boxShadow: [ | ||||
|             BoxShadow( | ||||
|                 spreadRadius: 2, | ||||
|                 blurRadius: 4, | ||||
|                 color: const Color(0xff1E293B).withOpacity(0.04) | ||||
|             ) | ||||
|           ] | ||||
|       ), | ||||
|       child: Wrap( | ||||
|         spacing: 10, | ||||
|         children: listPortofolioType.asMap().entries.map((e) { | ||||
|           return  GestureDetector( | ||||
|             onTap: () { | ||||
|               routePush(context, page: InvestTypeView(e.value.name)); | ||||
|             }, | ||||
|             child: Container( | ||||
|               color: Colors.white, | ||||
|               width: SizeConfig.width * .18, | ||||
|               child: Column( | ||||
|                 children: [ | ||||
|                   ImageView(image: e.value.iconImage, height: SizeConfig.width * .12, width: SizeConfig.width * .12,), | ||||
|                   const SizedBox( | ||||
|                     height: 8, | ||||
|                   ), | ||||
|                   Text( | ||||
|                     e.value.name, | ||||
|                     overflow: TextOverflow.ellipsis, | ||||
|                     textAlign: TextAlign.center, | ||||
|                     style: const TextStyle( | ||||
|                       fontSize: 12, | ||||
|                       fontWeight: FontWeight.w600 | ||||
|                     ), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
|         }).toList(), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget cardVerification() { | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.symmetric(horizontal: 24), | ||||
|       padding: const EdgeInsets.all(16), | ||||
|       decoration: BoxDecoration( | ||||
|         color: Colors.white, | ||||
|         borderRadius: BorderRadius.circular(12), | ||||
|       ), | ||||
|       child: Column( | ||||
|         children: [ | ||||
|           stepVerification(), | ||||
|           const SizedBox( | ||||
|             height: 24, | ||||
|           ), | ||||
|           Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               const Row( | ||||
|                 children: [ | ||||
|                   Icon(Icons.verified, size: 18,), | ||||
|                   SizedBox( | ||||
|                     width: 12, | ||||
|                   ), | ||||
|                   Text( | ||||
|                     'Verified by PT Gemilang', | ||||
|                     style: TextStyle( | ||||
|                       color: ColorPalette.slate500 | ||||
|                     ), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|               Container( | ||||
|                 width: 16, | ||||
|                 height: 16, | ||||
|                 decoration: BoxDecoration( | ||||
|                     color: Colors.white, | ||||
|                     border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), | ||||
|                     shape: BoxShape.circle | ||||
|                 ), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               const Row( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.end, | ||||
|                 children: [ | ||||
|                   Icon(Icons.verified, size: 18,), | ||||
|                   SizedBox( | ||||
|                     width: 12, | ||||
|                   ), | ||||
|                   Text( | ||||
|                     'Verified by KSEI', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate500 | ||||
|                     ), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|               Container( | ||||
|                 width: 16, | ||||
|                 height: 16, | ||||
|                 decoration: BoxDecoration( | ||||
|                     color: Colors.white, | ||||
|                     border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), | ||||
|                     shape: BoxShape.circle | ||||
|                 ), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           Container( | ||||
|             padding: const EdgeInsets.all(12), | ||||
|             decoration: BoxDecoration( | ||||
|                 color: const Color(0xffEFF6FF), | ||||
|                 borderRadius: BorderRadius.circular(12) | ||||
|             ), | ||||
|             child: const Column( | ||||
|               children: [ | ||||
|                 Text( | ||||
|                   'Your registration is currently being verified by PT Gemilang', | ||||
|                   style: TextStyle( | ||||
|                       color: ColorPalette.slate500 | ||||
|                   ), | ||||
|                 ), | ||||
|                 SizedBox( | ||||
|                   height: 16, | ||||
|                 ), | ||||
|                 Row( | ||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                   children: [ | ||||
|                     Text('Estimated:', | ||||
|                       style: TextStyle( | ||||
|                         color: ColorPalette.slate500 | ||||
|                       ), | ||||
|                     ), | ||||
|                     Text( | ||||
|                       'January 30 2024', | ||||
|                       style: TextStyle( | ||||
|                           fontWeight: FontWeight.w600, | ||||
|                           color: Color(0xff1E293B) | ||||
|                       ), | ||||
|                     ) | ||||
|                   ], | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget stepVerification() { | ||||
|     return Row( | ||||
|       mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|       children: listStepVerification.nameStep.asMap().entries.map((e) { | ||||
|         return Row( | ||||
|           crossAxisAlignment: CrossAxisAlignment.start, | ||||
|           children: [ | ||||
|             if(e.key != 0) | ||||
|               SizedBox( | ||||
|                 width: 30, | ||||
|                 height: 30, | ||||
|                 child: Divider(color: listStepVerification.currentStep >= e.key ? const Color(0xff2563EB) : const Color(0xffCBD5E1),), | ||||
|               ), | ||||
|             Column( | ||||
|               children: [ | ||||
|                 Container( | ||||
|                   width: 30, | ||||
|                   height: 30, | ||||
|                   decoration: BoxDecoration( | ||||
|                       shape: BoxShape.circle, | ||||
|                       color: listStepVerification.currentStep <= e.key ? Colors.white : const Color(0xff2563EB), | ||||
|                       border: Border.all( | ||||
|                           color: listStepVerification.currentStep < e.key ? const Color(0xffCBD5E1) : const Color(0xff2563EB), | ||||
|                           width: 2 | ||||
|                       ) | ||||
|                   ), | ||||
|                   child: listStepVerification.currentStep <= e.key ? const SizedBox() : const Icon(Icons.done_rounded, color: Colors.white,), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 8, | ||||
|                 ), | ||||
|                 Text(e.value, style: TextStyle(color: listStepVerification.currentStep == e.key ? const Color(0xff2563EB) : Colors.black),) | ||||
|               ], | ||||
|             ), | ||||
|           ], | ||||
|         ); | ||||
|       }).toList(), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget infoAndPromo() { | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|       child: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           const TextTitle(title: 'Info and Special Promo', color: ColorPalette.slate800,), | ||||
|           const SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           CarouselSlider( | ||||
|             items: [1,2,3].map((e) { | ||||
|               return Padding( | ||||
|                 padding: const EdgeInsets.symmetric(horizontal: 8), | ||||
|                 child: ImageView(image: PathAssets.imgCarousel, height: 150, width: SizeConfig.width * .9,), | ||||
|               ); | ||||
|             }).toList(), | ||||
|             options: CarouselOptions( | ||||
|               height: 150, | ||||
|               autoPlay: true, | ||||
|               pageSnapping: true, | ||||
|               viewportFraction: 0.9, | ||||
|               autoPlayInterval: const Duration(seconds: 5), | ||||
|               autoPlayCurve: Curves.fastOutSlowIn, | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget articles() { | ||||
|     return Container( | ||||
|       color: Colors.white, | ||||
|       padding: const EdgeInsets.symmetric(vertical: 24), | ||||
|       child: Column( | ||||
|         children: [ | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|             child: Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 const TextTitle(title: 'Article', color: ColorPalette.slate800), | ||||
|                 GestureDetector( | ||||
|                   onTap: () { | ||||
|  | ||||
|                   }, | ||||
|                   child: const Text('See More', | ||||
|                     style: TextStyle( | ||||
|                       color: ColorPalette.primary, | ||||
|                       fontWeight: FontWeight.bold | ||||
|                     ),), | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           ...listArticle.asMap().entries.map((e) { | ||||
|             return Column( | ||||
|               children: [ | ||||
|                 if(e.key != 0)...[ | ||||
|                   const Padding( | ||||
|                     padding: EdgeInsets.symmetric(vertical: 12), | ||||
|                     child: Divider(color: ColorPalette.slate200,), | ||||
|                   ) | ||||
|                 ], | ||||
|                 cardArticle(e.value), | ||||
|               ], | ||||
|             ); | ||||
|           }) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget cardArticle(Article article) { | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|       child: Row( | ||||
|         children: [ | ||||
|           ImageView(image: PathAssets.imgArticles, width: SizeConfig.width * .17, height: SizeConfig.height * .08, borderRadius: 8,), | ||||
|           const SizedBox( | ||||
|             width: 16, | ||||
|           ), | ||||
|           Expanded( | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 Text(article.title, | ||||
|                   style: const TextStyle( | ||||
|                     fontWeight: FontWeight.bold, | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 8, | ||||
|                 ), | ||||
|                 Container( | ||||
|                   padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12), | ||||
|                   decoration: BoxDecoration( | ||||
|                     borderRadius: BorderRadius.circular(30), | ||||
|                     color: ColorPalette.colorSwitchButtonActive | ||||
|                   ), | ||||
|                   child: Text(article.type), | ||||
|                 ), | ||||
|               ], | ||||
|             ) | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,229 @@ | ||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | ||||
| import 'package:cims_apps/application/component/button/button_back.dart'; | ||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | ||||
| import 'package:cims_apps/application/component/text_title/text_title.dart'; | ||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/core/route/route.dart'; | ||||
| import 'package:cims_apps/core/utils/size_config.dart'; | ||||
| import 'package:cims_apps/features/dashboard/dashboard_account/view/product/product_view.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class Product { | ||||
|   String name; | ||||
|   double yield; | ||||
|   double priceUnit; | ||||
|   double funds; | ||||
|    | ||||
|   Product(this.name, this.yield, this.priceUnit, this.funds); | ||||
| } | ||||
|  | ||||
| class InvestTypeView extends StatefulWidget { | ||||
|   final String title; | ||||
|   const InvestTypeView(this.title, {super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<InvestTypeView> createState() => _InvestTypeViewState(); | ||||
| } | ||||
|  | ||||
| class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|    | ||||
|   List<Product> listProduct = [ | ||||
|     Product('Gemilang Dana Kas Maxima', 8.17, 2600.79, 6300000), | ||||
|     Product('Gemilang Dana Likuid', 6.42, 1600.79, 2340000), | ||||
|     Product('Gemilang Income Fund', 8.17, 2600.79, 6300000) | ||||
|   ]; | ||||
|    | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       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: [ | ||||
|                       ButtonBack(), | ||||
|                       TextTitle(title: widget.title, color: Colors.white), | ||||
|                       SizedBox( | ||||
|                         width: SizeConfig.width * 0.1, | ||||
|                       ) | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 24, | ||||
|                 ), | ||||
|                 Container( | ||||
|                   padding: const EdgeInsets.all(24), | ||||
|                   decoration: BoxDecoration( | ||||
|                     borderRadius: BorderRadius.circular(16), | ||||
|                     color: Colors.white | ||||
|                   ), | ||||
|                   child: Column( | ||||
|                     children: [ | ||||
|                       filters(), | ||||
|                       ListView( | ||||
|                         shrinkWrap: true, | ||||
|                         children: listProduct.asMap().entries.map((e) { | ||||
|                           return GestureDetector( | ||||
|                             onTap: () { | ||||
|                               routePush(context, page: ProductView(widget.title)); | ||||
|                             }, | ||||
|                             child: Padding( | ||||
|                               padding: EdgeInsets.only(top: e.key != 0 ? 24 : 0), | ||||
|                               child: cardProduct(e.value), | ||||
|                             ), | ||||
|                           ); | ||||
|                         }).toList(), | ||||
|                       ) | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget filters() { | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 8), | ||||
|       child: Row( | ||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|         children: [ | ||||
|           segmentFilter(const Icon(Icons.filter_alt_outlined), 'Filter', () { }), | ||||
|           segmentFilter(const RotatedBox(quarterTurns: 1, child: Icon(Icons.compare_arrows)), 'Sort', () { }), | ||||
|           segmentFilter(const Icon(Icons.dashboard_outlined), 'Compare', () { }), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget segmentFilter(Widget leading, String text, void Function()? onTap) { | ||||
|     return GestureDetector( | ||||
|       onTap: onTap, | ||||
|       child:  Container( | ||||
|         padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), | ||||
|         decoration: BoxDecoration( | ||||
|             border: Border.all(color: ColorPalette.slate200), | ||||
|             borderRadius: BorderRadius.circular(56) | ||||
|         ), | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             leading, | ||||
|             const SizedBox( | ||||
|               width: 4, | ||||
|             ), | ||||
|             Text( | ||||
|               text, | ||||
|               overflow: TextOverflow.ellipsis, | ||||
|               style: const TextStyle( | ||||
|                 color: ColorPalette.slate500, | ||||
|                 fontWeight: FontWeight.w700 | ||||
|               ), | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget cardProduct(Product product) { | ||||
|     return Container( | ||||
|       padding: const EdgeInsets.all(16), | ||||
|       decoration: BoxDecoration( | ||||
|         borderRadius: BorderRadius.circular(12), | ||||
|         border: Border.all(color: ColorPalette.slate200), | ||||
|       ), | ||||
|       child: Column( | ||||
|         children: [ | ||||
|           Row( | ||||
|             children: [ | ||||
|               Text( | ||||
|                 product.name, | ||||
|                 style: TextStyle( | ||||
|                   fontWeight: FontWeight.bold, | ||||
|                   fontSize: 18 | ||||
|                 ), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|           const Padding( | ||||
|             padding: EdgeInsets.symmetric(vertical: 12), | ||||
|             child: Divider(color: ColorPalette.slate200), | ||||
|           ), | ||||
|           Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   Text('Yield', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),), | ||||
|                   Row( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         '${product.yield.toString()}%', | ||||
|                         style: TextStyle( | ||||
|                           color: ColorPalette.green400, | ||||
|                           fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                       ), | ||||
|                       Text('/'), | ||||
|                       Text('3year', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),) | ||||
|                     ], | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   Text('Price/unit', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),), | ||||
|                   Row( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         'Rp${product.priceUnit.toString()}', | ||||
|                         style: TextStyle( | ||||
|                           fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                       ), | ||||
|                       SizedBox( | ||||
|                         width: 2, | ||||
|                       ), | ||||
|                       Icon(Icons.trending_up_outlined, size: 18, color: ColorPalette.green400,) | ||||
|                     ], | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   Text('Managed funds', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),), | ||||
|                   Row( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         product.funds.toString(), | ||||
|                         style: TextStyle( | ||||
|                             fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ) | ||||
|                 ], | ||||
|               ) | ||||
|             ], | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,347 @@ | ||||
| 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:fl_chart/fl_chart.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class CategoryPortofolio { | ||||
|   String name; | ||||
|   int value; | ||||
|  | ||||
|   CategoryPortofolio(this.value, this.name); | ||||
| } | ||||
|  | ||||
| class PortofolioView extends StatefulWidget { | ||||
|   const PortofolioView({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<PortofolioView> createState() => _PortofolioViewState(); | ||||
| } | ||||
|  | ||||
| class _PortofolioViewState extends State<PortofolioView> { | ||||
|   List<Color> contentColor = [ | ||||
|     ColorPalette.purple500, | ||||
|     ColorPalette.orange500, | ||||
|     ColorPalette.cyan500, | ||||
|     ColorPalette.green500, | ||||
|   ]; | ||||
|   List<Color> bgContentColor = [ | ||||
|     ColorPalette.purple100, | ||||
|     ColorPalette.orange100, | ||||
|     ColorPalette.cyan100, | ||||
|     ColorPalette.green100, | ||||
|   ]; | ||||
|  | ||||
|   bool seePortofolioValue = false; | ||||
|   int touchedIndex = -1; | ||||
|  | ||||
|   List<CategoryPortofolio> listCategoryPortofolio = [ | ||||
|     CategoryPortofolio(20, 'Money Market'), | ||||
|     CategoryPortofolio(15, 'Shares'), | ||||
|     CategoryPortofolio(8, 'Bonds'), | ||||
|     CategoryPortofolio(50, 'Sharia'), | ||||
|   ]; | ||||
|  | ||||
|   List<String> assetsImage = [ | ||||
|     PathAssets.iconPortofolioMoneyMarket, | ||||
|     PathAssets.iconPortofolioShares, | ||||
|     PathAssets.iconPortofolioBonds, | ||||
|     PathAssets.iconPortofolioSharia, | ||||
|   ]; | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return 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, | ||||
|                 ), | ||||
|                 const Center( | ||||
|                   child: Text( | ||||
|                     'Portofolio', | ||||
|                     style: TextStyle( | ||||
|                         fontSize: 20, | ||||
|                         fontWeight: FontWeight.w700, | ||||
|                         color: Colors.white), | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 40, | ||||
|                 ), | ||||
|                 Padding( | ||||
|                   padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|                   child: portofolioValue(), | ||||
|                 ), | ||||
|                 Expanded( | ||||
|                   child: Container( | ||||
|                     margin: const EdgeInsets.only(top: 24), | ||||
|                     decoration: const BoxDecoration( | ||||
|                       color: Colors.white, | ||||
|                       borderRadius: BorderRadius.only( | ||||
|                           topLeft: Radius.circular(24), | ||||
|                           topRight: Radius.circular(24)), | ||||
|                     ), | ||||
|                     child: ListView( | ||||
|                       padding: const EdgeInsets.symmetric(vertical: 0), | ||||
|                       children: [ | ||||
|                         Stack(alignment: Alignment.center, children: [ | ||||
|                           AspectRatio( | ||||
|                             aspectRatio: 1.3, | ||||
|                             child: PieChart(PieChartData( | ||||
|                                 pieTouchData: PieTouchData( | ||||
|                                   touchCallback: | ||||
|                                       (FlTouchEvent event, pieTouchResponse) { | ||||
|                                     setState(() { | ||||
|                                       if (!event.isInterestedForInteractions || | ||||
|                                           pieTouchResponse == null || | ||||
|                                           pieTouchResponse.touchedSection == | ||||
|                                               null) { | ||||
|                                         touchedIndex = -1; | ||||
|                                         return; | ||||
|                                       } | ||||
|                                       touchedIndex = pieTouchResponse | ||||
|                                           .touchedSection!.touchedSectionIndex; | ||||
|                                     }); | ||||
|                                   }, | ||||
|                                 ), | ||||
|                                 borderData: FlBorderData( | ||||
|                                   show: true, | ||||
|                                 ), | ||||
|                                 sectionsSpace: 20, | ||||
|                                 centerSpaceRadius: 100, | ||||
|                                 sections: sectionsDataPortofolio())), | ||||
|                           ), | ||||
|                           const Column( | ||||
|                             children: [ | ||||
|                               Text('Total Mutual Fund'), | ||||
|                               Text('10', | ||||
|                                   style: TextStyle( | ||||
|                                       fontSize: 44, | ||||
|                                       fontWeight: FontWeight.w700)), | ||||
|                             ], | ||||
|                           ) | ||||
|                         ]), | ||||
|                         const SizedBox( | ||||
|                           height: 12, | ||||
|                         ), | ||||
|                         menuPortofolio(), | ||||
|                         const SizedBox( | ||||
|                           height: 24, | ||||
|                         ), | ||||
|                         ...listColumnPortofolio(), | ||||
|                         const SizedBox( | ||||
|                           height: 24, | ||||
|                         ) | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ) | ||||
|               ], | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget portofolioValue() { | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         Row( | ||||
|           children: [ | ||||
|             const Text('Portofolio Value', | ||||
|                 style: TextStyle(color: Colors.white)), | ||||
|             const SizedBox( | ||||
|               width: 8, | ||||
|             ), | ||||
|             GestureDetector( | ||||
|                 onTap: () { | ||||
|                   setState(() { | ||||
|                     seePortofolioValue = !seePortofolioValue; | ||||
|                   }); | ||||
|                 }, | ||||
|                 child: const Icon(Icons.visibility_outlined, | ||||
|                     color: Color(0xff93C5FD))) | ||||
|           ], | ||||
|         ), | ||||
|         const SizedBox( | ||||
|           height: 4, | ||||
|         ), | ||||
|         Row( | ||||
|           children: [ | ||||
|             AnimatedCrossFade( | ||||
|               duration: const Duration(milliseconds: 300), | ||||
|               alignment: Alignment.center, | ||||
|               crossFadeState: seePortofolioValue | ||||
|                   ? CrossFadeState.showSecond | ||||
|                   : CrossFadeState.showFirst, | ||||
|               firstChild: RichText( | ||||
|                   text: const TextSpan( | ||||
|                       text: 'Rp ', | ||||
|                       style: TextStyle(fontSize: 32, color: Color(0xff93C5FD), fontFamily: 'Manrope'), | ||||
|                       children: [ | ||||
|                     TextSpan( | ||||
|                       text: '22.500.000', | ||||
|                       style: TextStyle( | ||||
|                           fontSize: 32, | ||||
|                           fontFamily: 'Manrope', | ||||
|                           fontWeight: FontWeight.bold, | ||||
|                           color: Colors.white | ||||
|                       ), | ||||
|                     ) | ||||
|                   ])), | ||||
|               secondChild: Padding( | ||||
|                 padding: const EdgeInsets.symmetric(vertical: 16), | ||||
|                 child: Wrap( | ||||
|                   spacing: 7, | ||||
|                   children: [ | ||||
|                     for (int i = 0; i < 6; i++) | ||||
|                       Container( | ||||
|                         width: 12, | ||||
|                         height: 12, | ||||
|                         decoration: const BoxDecoration( | ||||
|                             color: Colors.white, shape: BoxShape.circle), | ||||
|                       ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ], | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   List<PieChartSectionData> sectionsDataPortofolio() { | ||||
|     return listCategoryPortofolio.asMap().entries.map((e) { | ||||
|       final isTouched = e.key == touchedIndex; | ||||
|       final radius = isTouched ? 40.0 : 30.0; | ||||
|       return PieChartSectionData( | ||||
|         color: contentColor[e.key], | ||||
|         value: e.value.value.toDouble(), | ||||
|         title: e.value.name, | ||||
|         showTitle: isTouched, | ||||
|         radius: radius, | ||||
|         titleStyle: const TextStyle( | ||||
|           fontSize: 20, | ||||
|           fontWeight: FontWeight.bold, | ||||
|         ), | ||||
|       ); | ||||
|     }).toList(); | ||||
|   } | ||||
|  | ||||
|   Widget menuPortofolio() { | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.symmetric(horizontal: 24), | ||||
|       padding: const EdgeInsets.all(12), | ||||
|       decoration: BoxDecoration( | ||||
|           color: Colors.white, | ||||
|           borderRadius: const BorderRadius.all(Radius.circular(12)), | ||||
|           boxShadow: [ | ||||
|             BoxShadow( | ||||
|                 spreadRadius: 2, | ||||
|                 blurRadius: 8, | ||||
|                 color: const Color(0xff1E293B).withOpacity(0.04)) | ||||
|           ]), | ||||
|       child: Wrap( | ||||
|         alignment: WrapAlignment.center, | ||||
|         spacing: 12, | ||||
|         children: listCategoryPortofolio.asMap().entries.map((e) { | ||||
|           return Container( | ||||
|             color: Colors.white, | ||||
|             width: SizeConfig.width * 0.18, | ||||
|             child: Column( | ||||
|               children: [ | ||||
|                 Container( | ||||
|                   height: 58, | ||||
|                   width: 58, | ||||
|                   alignment: Alignment.center, | ||||
|                   decoration: BoxDecoration( | ||||
|                       shape: BoxShape.circle, | ||||
|                       color: bgContentColor[e.key], | ||||
|                   ), | ||||
|                   child: Text( | ||||
|                     '${e.value.value}%', | ||||
|                     style: TextStyle( | ||||
|                         fontWeight: FontWeight.bold, | ||||
|                         color: contentColor[e.key]), | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 8, | ||||
|                 ), | ||||
|                 Text( | ||||
|                   e.value.name, | ||||
|                   overflow: TextOverflow.ellipsis, | ||||
|                   textAlign: TextAlign.center, | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|           ); | ||||
|         }).toList(), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   List<Widget> listColumnPortofolio() { | ||||
|     return listCategoryPortofolio.asMap().entries.map((e) { | ||||
|       return Column( | ||||
|         children: [ | ||||
|           if (e.key > 0) ...[ | ||||
|             const Divider( | ||||
|               color: ColorPalette.slate200, | ||||
|             ) | ||||
|           ], | ||||
|           ListTile( | ||||
|             contentPadding: | ||||
|                 const EdgeInsets.symmetric(vertical: 0, horizontal: 24), | ||||
|             leading: ImageView( | ||||
|               image: assetsImage[e.key], | ||||
|               width: SizeConfig.width * .15, | ||||
|               height: SizeConfig.height * .08, | ||||
|               borderRadius: 8, | ||||
|             ), | ||||
|             title: Text( | ||||
|               e.value.name, | ||||
|               style: const TextStyle(fontWeight: FontWeight.w600), | ||||
|             ), | ||||
|             subtitle: Text( | ||||
|               e.value.name, | ||||
|               style: const TextStyle( | ||||
|                   fontWeight: FontWeight.w600, color: Color(0xff94A3B8)), | ||||
|             ), | ||||
|             trailing: const Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.end, | ||||
|               children: [ | ||||
|                 Text( | ||||
|                   'Rp 2.000.000', | ||||
|                   style: TextStyle( | ||||
|                       color: Colors.black, | ||||
|                       fontSize: 16, | ||||
|                       fontWeight: FontWeight.w700), | ||||
|                 ), | ||||
|                 Text( | ||||
|                   '+ Rp 200.000', | ||||
|                   style: TextStyle( | ||||
|                       fontSize: 14, | ||||
|                       color: Color(0xff4ADE80), | ||||
|                       fontWeight: FontWeight.w600), | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ); | ||||
|     }).toList(); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,433 @@ | ||||
| import 'dart:math'; | ||||
|  | ||||
| import 'package:cims_apps/application/assets/path_assets.dart'; | ||||
| import 'package:cims_apps/application/component/button/button_back.dart'; | ||||
| import 'package:cims_apps/application/component/image/image_view.dart'; | ||||
| import 'package:cims_apps/application/component/text_title/text_title.dart'; | ||||
| import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/core/utils/size_config.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class ProductView extends StatefulWidget { | ||||
|   final String investType; | ||||
|   const ProductView(this.investType, {super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<ProductView> createState() => _ProductViewState(); | ||||
| } | ||||
|  | ||||
| class _ProductViewState extends State<ProductView> { | ||||
|   int chooseTab = 0; | ||||
|   String chooseTime = '1Y'; | ||||
|   int chooseMachine = 0; | ||||
|  | ||||
|   List<String> listTime = ['1D', '1M', '3M', 'YTD', '1Y', '3Y', '5Y', '10Y', 'All']; | ||||
|  | ||||
|   List<String> listTab = ['NAV', 'AUM']; | ||||
|  | ||||
|   List<String> listMachine = ['Monthly Routine', 'Connect Once']; | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       body: SizedBox( | ||||
|         width: SizeConfig.width, | ||||
|         height: SizeConfig.height, | ||||
|         child: Stack( | ||||
|           children: [ | ||||
|             const ImageView(image: PathAssets.imgDashboardAccount), | ||||
|             Column( | ||||
|               children: [ | ||||
|                 const SizedBox( | ||||
|                   height: 50, | ||||
|                 ), | ||||
|                 const Padding( | ||||
|                   padding: EdgeInsets.symmetric(horizontal: 24), | ||||
|                   child: Row( | ||||
|                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                     children: [ | ||||
|                       ButtonBack(), | ||||
|                       Wrap( | ||||
|                         spacing: 12, | ||||
|                         children: [ | ||||
|                           Icon(Icons.search_rounded, color: ColorPalette.blue200, size: 32), | ||||
|                           Icon(Icons.file_download_outlined, color: ColorPalette.blue200, size: 32), | ||||
|                           Icon(Icons.star_outline_rounded, color: ColorPalette.blue200, size: 32) | ||||
|                         ], | ||||
|                       ) | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SizedBox( | ||||
|                   height: 24, | ||||
|                 ), | ||||
|                 headContainer(), | ||||
|                 const SizedBox( | ||||
|                   height: 24, | ||||
|                 ), | ||||
|                 Expanded( | ||||
|                   child: contentContainer() | ||||
|                 ) | ||||
|               ], | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget headContainer() { | ||||
|     return Padding( | ||||
|         padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|         child: Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             const Expanded( | ||||
|               child: Row( | ||||
|                 children: [ | ||||
|                   Expanded( | ||||
|                     child: Text( | ||||
|                       'Gemilang Dana Kas Maxima', | ||||
|                       style: TextStyle( | ||||
|                           color: Colors.white, | ||||
|                           fontWeight: FontWeight.w700, | ||||
|                           fontSize: 18 | ||||
|                       ), | ||||
|                     ), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|             Container( | ||||
|               padding: const EdgeInsets.all(6), | ||||
|               decoration: BoxDecoration( | ||||
|                   borderRadius: BorderRadius.circular(40), | ||||
|                   color: ColorPalette.investTypeBgColor[widget.investType] ?? Colors.white, | ||||
|                   border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.investType] ?? Colors.white) | ||||
|               ), | ||||
|               child: Text( | ||||
|                 widget.investType, | ||||
|                 style: TextStyle( | ||||
|                     color: ColorPalette.investTypeColor[widget.investType], | ||||
|                     fontWeight: FontWeight.w600 | ||||
|                 ), | ||||
|               ), | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   Widget contentContainer() { | ||||
|     return Container( | ||||
|       decoration: BoxDecoration( | ||||
|         borderRadius: BorderRadius.circular(12), | ||||
|         color: Colors.white, | ||||
|       ), | ||||
|       child: ListView( | ||||
|         children: [ | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|             child: Wrap( | ||||
|               spacing: 8, | ||||
|               children: [ | ||||
|                 Text(listTab[chooseTab]), | ||||
|                 const Text('26 Jan 24'), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           Center( | ||||
|             child: Padding( | ||||
|               padding: const EdgeInsets.all(24), | ||||
|               child: switchTab(listTab, (value) { | ||||
|                 setState(() { | ||||
|                   chooseTab = value; | ||||
|                 }); | ||||
|               }, chooseTab), | ||||
|             ), | ||||
|           ), | ||||
|           swithTime(), | ||||
|           const SizedBox( | ||||
|           height: 24, | ||||
|           ), | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|             child: Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 columnInformation('CAGR 1Y', '3,88%'), | ||||
|                 columnInformation('Drawdown 1Y', '0%'), | ||||
|                 columnInformation('Expense Ratio', '1,99%') | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|             child: Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 columnInformation('Total AUM', '3,88%'), | ||||
|                 columnInformation('Avg.Yield Dec 23', '0%'), | ||||
|                 columnInformation('Risk Level', '1,99%') | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             height: 24, | ||||
|           ), | ||||
|           cardInformation('Informasi Investasi', informationInvest()), | ||||
|           const SizedBox( | ||||
|             height: 24, | ||||
|           ), | ||||
|           cardInformation('Informasi Investasi', investCost()), | ||||
|           const SizedBox( | ||||
|             height: 24, | ||||
|           ), | ||||
|           cardInformation('Time Machine', timeMachine()) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget switchTab(List<String> dataTab, void Function(int value) onTap, int current) { | ||||
|     return Container( | ||||
|       width: SizeConfig.width, | ||||
|       decoration: BoxDecoration( | ||||
|         border: Border.all( | ||||
|           color: ColorPalette.slate200, | ||||
|         ), | ||||
|         borderRadius: BorderRadius.circular(80) | ||||
|       ), | ||||
|       child: Stack( | ||||
|         children: [ | ||||
|           // AnimatedPositioned( | ||||
|           //   duration: const Duration(milliseconds: 200), | ||||
|           //   curve: Curves.fastOutSlowIn, | ||||
|           //   right: current == dataTab.length - 1 ? 0 : SizeConfig.width * current / dataTab.length - (12 * dataTab.length), | ||||
|           //   left:  current == 0 ? 0 : SizeConfig.width * current / dataTab.length - (12 * dataTab.length), | ||||
|           //   child: Container( | ||||
|           //     height: 35, | ||||
|           //     decoration: BoxDecoration( | ||||
|           //       color: ColorPalette.blue200, | ||||
|           //       borderRadius: BorderRadius.circular(80) | ||||
|           //     ), | ||||
|           //   ), | ||||
|           // ), | ||||
|           Container( | ||||
|             height: 35, | ||||
|             decoration: BoxDecoration( | ||||
|               borderRadius: BorderRadius.circular(80) | ||||
|             ), | ||||
|             child: Row( | ||||
|               children: dataTab.asMap().entries.map((e) => Expanded( | ||||
|                   child: GestureDetector( | ||||
|                       onTap: () { | ||||
|                         onTap(e.key); | ||||
|                       }, | ||||
|                       child: AnimatedContainer( | ||||
|                         duration: Duration(milliseconds: 300), | ||||
|                         height: 35, | ||||
|                         alignment: Alignment.center, | ||||
|                         decoration: BoxDecoration( | ||||
|                           borderRadius: BorderRadius.circular(80), | ||||
|                           color: e.key == current ? ColorPalette.blue200 : ColorPalette.white | ||||
|                         ), | ||||
|                         child: Text( | ||||
|                           e.value, | ||||
|                           textAlign: TextAlign.center, | ||||
|                           style: TextStyle( | ||||
|                             fontWeight: e.key == current ? FontWeight.w700 : FontWeight.w500, | ||||
|                             color: e.key == current ? ColorPalette.primary : ColorPalette.slate500 | ||||
|                           ), | ||||
|                         ), | ||||
|                       ) | ||||
|                   ) | ||||
|               )).toList(), | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget swithTime() { | ||||
|     return Container( | ||||
|         color: ColorPalette.slate50, | ||||
|         child: SingleChildScrollView( | ||||
|           scrollDirection: Axis.horizontal, | ||||
|           padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           child: Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.center, | ||||
|             children: listTime.map((e) { | ||||
|               return GestureDetector( | ||||
|                 onTap: () { | ||||
|                   setState(() { | ||||
|                     chooseTime = e; | ||||
|                   }); | ||||
|                 }, | ||||
|                 child: AnimatedContainer( | ||||
|                   duration: const Duration(milliseconds: 200), | ||||
|                   width: SizeConfig.width * .12, | ||||
|                   alignment: Alignment.center, | ||||
|                   padding: const EdgeInsets.symmetric(vertical: 4), | ||||
|                   decoration: BoxDecoration( | ||||
|                       borderRadius: BorderRadius.circular(4), | ||||
|                       color: chooseTime == e ? ColorPalette.primary : ColorPalette.slate50 | ||||
|                   ), | ||||
|                   child: Text(e, style: TextStyle( | ||||
|                       color: chooseTime == e ? ColorPalette.white : ColorPalette.slate400, | ||||
|                       fontWeight: FontWeight.w700 | ||||
|                   )), | ||||
|                 ), | ||||
|               ); | ||||
|             }).toList(), | ||||
|           ), | ||||
|         ) | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget columnInformation(String title, String value) { | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.center, | ||||
|       children: [ | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.center, | ||||
|           children: [ | ||||
|             Text( | ||||
|               title, | ||||
|               maxLines: 1, | ||||
|               style: const TextStyle( | ||||
|                 color: ColorPalette.slate400 | ||||
|               ), | ||||
|             ), | ||||
|             const SizedBox(width: 2), | ||||
|             const Icon(Icons.info_outline_rounded, size: 16, color: ColorPalette.slate400) | ||||
|           ], | ||||
|         ), | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.center, | ||||
|           children: [ | ||||
|             Text(value) | ||||
|           ], | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|    | ||||
|   Widget cardInformation(String title, Widget child) { | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.symmetric(horizontal: 24), | ||||
|       padding: const EdgeInsets.all(16), | ||||
|       decoration: BoxDecoration( | ||||
|         border: Border.all(color: ColorPalette.slate200), | ||||
|         borderRadius: BorderRadius.circular(12) | ||||
|       ), | ||||
|       child: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           TextTitle(title: title, fontSize: 16), | ||||
|           SizedBox( | ||||
|             height: 16, | ||||
|           ), | ||||
|           child | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget informationInvest() { | ||||
|     return const Column( | ||||
|       children: [ | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             Text( | ||||
|               'Minimum Purchase', | ||||
|               style: TextStyle( | ||||
|                 color: ColorPalette.slate400, | ||||
|                 fontWeight: FontWeight.w600 | ||||
|               ), | ||||
|             ), | ||||
|             Text('Rp10.000') | ||||
|           ], | ||||
|         ), | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             Text( | ||||
|               'Custodian Bank', | ||||
|               style: TextStyle( | ||||
|                   color: ColorPalette.slate400, | ||||
|                   fontWeight: FontWeight.w600 | ||||
|               ), | ||||
|             ), | ||||
|             Text('HSBC INDONESIA') | ||||
|           ], | ||||
|         ), | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             Text( | ||||
|               'Depository Bank', | ||||
|               style: TextStyle( | ||||
|                   color: ColorPalette.slate400, | ||||
|                   fontWeight: FontWeight.w600 | ||||
|               ), | ||||
|             ), | ||||
|             Text('BCA') | ||||
|           ], | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget investCost(){ | ||||
|     return const Column( | ||||
|       children: [ | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             Text( | ||||
|               'Purchase Commission', | ||||
|               style: TextStyle( | ||||
|                   color: ColorPalette.slate400, | ||||
|                   fontWeight: FontWeight.w600 | ||||
|               ), | ||||
|             ), | ||||
|             Text('Free') | ||||
|           ], | ||||
|         ), | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|           children: [ | ||||
|             Text( | ||||
|               'Sales Commission', | ||||
|               style: TextStyle( | ||||
|                   color: ColorPalette.slate400, | ||||
|                   fontWeight: FontWeight.w600 | ||||
|               ), | ||||
|             ), | ||||
|             Text('Free') | ||||
|           ], | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget timeMachine() { | ||||
|     return Column( | ||||
|       children: [ | ||||
|         switchTab(listMachine, (value) { | ||||
|             setState(() { | ||||
|               chooseMachine = value; | ||||
|             }); | ||||
|           }, | ||||
|           chooseMachine | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -5,6 +5,7 @@ import 'package:cims_apps/application/theme/color_palette.dart'; | ||||
| import 'package:cims_apps/core/route/route.dart'; | ||||
| import 'package:cims_apps/core/utils/size_config.dart'; | ||||
| import 'package:cims_apps/features/auth/registration/view/registration_view.dart'; | ||||
| import 'package:cims_apps/features/bottom_navigation_view.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class DashboardPublicView extends StatelessWidget { | ||||
| @@ -68,7 +69,9 @@ class DashboardPublicView extends StatelessWidget { | ||||
|                   isOutlined: true, | ||||
|                   width: SizeConfig.width * .43, | ||||
|                   height: SizeConfig.height * .06, | ||||
|                   onPressed: () {}, | ||||
|                   onPressed: () { | ||||
|                     routePush(context, page: const BottomNavigationView()); | ||||
|                   }, | ||||
|                 ), | ||||
|                 ButtonView( | ||||
|                   name: 'Sign Up', | ||||
|   | ||||
							
								
								
									
										48
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						| @@ -49,6 +49,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.1.1" | ||||
|   carousel_slider: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: carousel_slider | ||||
|       sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.2.1" | ||||
|   characters: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -97,6 +105,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.6" | ||||
|   equatable: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: equatable | ||||
|       sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.0.5" | ||||
|   fake_async: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -129,6 +145,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.1.0" | ||||
|   fl_chart: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: fl_chart | ||||
|       sha256: "5a74434cc83bf64346efb562f1a06eefaf1bcb530dc3d96a104f631a1eff8d79" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.65.0" | ||||
|   flutter: | ||||
|     dependency: "direct main" | ||||
|     description: flutter | ||||
| @@ -179,6 +203,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.0.2" | ||||
|   intl: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: intl | ||||
|       sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.19.0" | ||||
|   js: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -227,6 +259,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.10.0" | ||||
|   nested: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: nested | ||||
|       sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.0" | ||||
|   octo_image: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -339,6 +379,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.7.4" | ||||
|   provider: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: provider | ||||
|       sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "6.1.1" | ||||
|   remove_emoji_input_formatter: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|   | ||||
| @@ -39,6 +39,10 @@ dependencies: | ||||
|   flutter_svg: ^1.1.6 | ||||
|   cached_network_image: ^3.2.3 | ||||
|   remove_emoji_input_formatter: ^0.0.1+1 | ||||
|   fl_chart: ^0.65.0 | ||||
|   intl: ^0.19.0 | ||||
|   carousel_slider: ^4.2.1 | ||||
|   provider: ^6.1.1 | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||