feat: flow subscribe product
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-bag.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-car.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-cart.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-gadget.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-market.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-plane.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/icon-ticket.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-open-shopping.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 101 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/img-payment-success.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 74 KiB  | 
@@ -39,6 +39,13 @@ class PathAssets {
 | 
			
		||||
  static const String iconCreatePlan = 'assets/icons/icon-create-plan.png';
 | 
			
		||||
  static const String iconThumb = 'assets/icons/icon-thumb.png';
 | 
			
		||||
  static const String iconPortofolio = 'assets/icons/icon-portofolio.png';
 | 
			
		||||
  static const String iconPlane = 'assets/icons/icon-plane.png';
 | 
			
		||||
  static const String iconCart = 'assets/icons/icon-cart.png';
 | 
			
		||||
  static const String iconBag = 'assets/icons/icon-bag.png';
 | 
			
		||||
  static const String iconMarket = 'assets/icons/icon-market.png';
 | 
			
		||||
  static const String iconTicket = 'assets/icons/icon-ticket.png';
 | 
			
		||||
  static const String iconGadget = 'assets/icons/icon-gadget.png';
 | 
			
		||||
  static const String iconCar = 'assets/icons/icon-car.png';
 | 
			
		||||
 | 
			
		||||
  /// IMAGE
 | 
			
		||||
  static const String imgSplashLogo = 'assets/images/splash-logo.png';
 | 
			
		||||
@@ -72,4 +79,6 @@ class PathAssets {
 | 
			
		||||
  static const String imgGuideBank = 'assets/images/img-guide-bank.png';
 | 
			
		||||
  static const String imgGuide1 = 'assets/images/img-guide1.png';
 | 
			
		||||
  static const String imgGuide2 = 'assets/images/img-guide2.png';
 | 
			
		||||
  static const String imgOpenShopping = 'assets/images/img-open-shopping.png';
 | 
			
		||||
  static const String imgPaymentSuccess = 'assets/images/img-payment-success.png';
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								lib/application/component/modal_redirect_app.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,41 @@
 | 
			
		||||
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:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class TypeApp {
 | 
			
		||||
  String img, title;
 | 
			
		||||
 | 
			
		||||
  TypeApp(this.img, this.title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ModalRedirectApp extends StatelessWidget {
 | 
			
		||||
  final String value;
 | 
			
		||||
  const ModalRedirectApp({super.key, required this.value});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    Map<String, TypeApp> typeApp = {
 | 
			
		||||
      'Shopping Pay': TypeApp(PathAssets.imgOpenShopping, 'Shopping App'),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return Column(
 | 
			
		||||
      children: [
 | 
			
		||||
        ImageView(image: typeApp[value]!.img),
 | 
			
		||||
        Text('Open ${typeApp[value]!.title}',
 | 
			
		||||
          style: TextStyle(
 | 
			
		||||
            fontSize: 22,
 | 
			
		||||
            fontWeight: FontWeight.w600,
 | 
			
		||||
            color: ColorPalette.slate800
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        Text('You will be redirected to the ${typeApp[value]!.title.toLowerCase()} to continue the payment',
 | 
			
		||||
          style: TextStyle(
 | 
			
		||||
              fontSize: 16,
 | 
			
		||||
              color: ColorPalette.slate400
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
import 'package:cims_apps/application/assets/path_assets.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/other_plan_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/route/route.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +22,7 @@ class GoalInvestingView extends StatelessWidget {
 | 
			
		||||
      GoalInvest(PathAssets.iconToga, 'Education'),
 | 
			
		||||
      GoalInvest(PathAssets.iconCake, 'Marriage'),
 | 
			
		||||
      GoalInvest(PathAssets.iconHouse, 'Old age days'),
 | 
			
		||||
      GoalInvest(PathAssets.iconCreatePlan, 'Create Plan'),
 | 
			
		||||
      GoalInvest(PathAssets.iconCreatePlan, 'Other Plan'),
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return Column(
 | 
			
		||||
@@ -30,7 +32,18 @@ class GoalInvestingView extends StatelessWidget {
 | 
			
		||||
            padding: EdgeInsets.only(top: e.key != 0 ? 16 : 0),
 | 
			
		||||
            child: ListTile(
 | 
			
		||||
              onTap: () {
 | 
			
		||||
                onListSelected(e.value.title);
 | 
			
		||||
                if(e.value.title == 'Other Plan'){
 | 
			
		||||
                  routePush(
 | 
			
		||||
                    context,
 | 
			
		||||
                    page: OtherPlanView(
 | 
			
		||||
                      selectedPlan: (value) {
 | 
			
		||||
                        onListSelected(e.value.title);
 | 
			
		||||
                      },
 | 
			
		||||
                    )
 | 
			
		||||
                  );
 | 
			
		||||
                }else{
 | 
			
		||||
                  onListSelected(e.value.title);
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              shape: RoundedRectangleBorder(
 | 
			
		||||
                side: BorderSide(color: ColorPalette.slate200),
 | 
			
		||||
@@ -51,10 +64,11 @@ class GoalInvestingView extends StatelessWidget {
 | 
			
		||||
              title: Text(e.value.title,
 | 
			
		||||
                style: TextStyle(
 | 
			
		||||
                  fontWeight: FontWeight.w600,
 | 
			
		||||
                  fontSize: 16
 | 
			
		||||
                  fontSize: 16,
 | 
			
		||||
                  color: ColorPalette.slate800
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              trailing: Icon(Icons.chevron_right_rounded),
 | 
			
		||||
              trailing: Icon(Icons.chevron_right_rounded, color: ColorPalette.slate400),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        }).toList()
 | 
			
		||||
							
								
								
									
										143
									
								
								lib/application/component/subscribe/input_investment_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,143 @@
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/number_formatter.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class InputInvestmentView extends StatefulWidget {
 | 
			
		||||
  final String selectedPlan;
 | 
			
		||||
  final void Function(String value) nextMove;
 | 
			
		||||
  const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<InputInvestmentView> createState() => _InputInvestmentViewState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _InputInvestmentViewState extends State<InputInvestmentView> {
 | 
			
		||||
  TextEditingController inputController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    inputController.text = 'Rp 0';
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    // TODO: implement dispose
 | 
			
		||||
    super.dispose();
 | 
			
		||||
    inputController.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Container(
 | 
			
		||||
      decoration: BoxDecoration(
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          borderRadius: BorderRadius.circular(16)
 | 
			
		||||
      ),
 | 
			
		||||
      child: Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        children: [
 | 
			
		||||
          SizedBox(height: 16),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
 | 
			
		||||
            child: Column(
 | 
			
		||||
              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
              children: [
 | 
			
		||||
                Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Text(widget.selectedPlan,
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        fontSize: 20,
 | 
			
		||||
                        fontWeight: FontWeight.w700,
 | 
			
		||||
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    Row(
 | 
			
		||||
                      children: [
 | 
			
		||||
                        Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
 | 
			
		||||
                        SizedBox(width: 4),
 | 
			
		||||
                        Text('Change',
 | 
			
		||||
                          style: TextStyle(
 | 
			
		||||
                              fontSize: 16,
 | 
			
		||||
                              fontWeight: FontWeight.w600,
 | 
			
		||||
                              color: ColorPalette.primary
 | 
			
		||||
                          ),
 | 
			
		||||
                        )
 | 
			
		||||
                      ],
 | 
			
		||||
                    )
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                TextField(
 | 
			
		||||
                  controller: inputController,
 | 
			
		||||
                  textAlign: TextAlign.center,
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      fontSize: 28,
 | 
			
		||||
                      fontWeight: FontWeight.w600,
 | 
			
		||||
                      color: ColorPalette.slate800
 | 
			
		||||
                  ),
 | 
			
		||||
                  keyboardType: TextInputType.number,
 | 
			
		||||
                  onChanged: (value) {
 | 
			
		||||
                    value = value.replaceAll('Rp ', '').replaceAll('.', '');
 | 
			
		||||
                    double parseValue = double.parse(value);
 | 
			
		||||
                    if(value.isNotEmpty){
 | 
			
		||||
                      inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
 | 
			
		||||
                    }else{
 | 
			
		||||
                      inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
 | 
			
		||||
                    }
 | 
			
		||||
                  },
 | 
			
		||||
                  decoration: InputDecoration(
 | 
			
		||||
                      enabledBorder: UnderlineInputBorder(
 | 
			
		||||
                        borderSide: BorderSide(
 | 
			
		||||
                            color: ColorPalette.primary,
 | 
			
		||||
                            width: 2
 | 
			
		||||
                        ),
 | 
			
		||||
                      )
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                SizedBox(height: 12),
 | 
			
		||||
                Text('Minimum Budget Rp1,000,000',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.slate400,
 | 
			
		||||
                      fontSize: 16,
 | 
			
		||||
                      fontWeight: FontWeight.w600
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                SizedBox(height: 16),
 | 
			
		||||
                NumericPad(onNumberSelected: (p0) {
 | 
			
		||||
                  String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', '');
 | 
			
		||||
                  String getNumeric = p0;
 | 
			
		||||
                  if(p0.isNotEmpty){
 | 
			
		||||
                    if(checkIsZeroInput != '0'){
 | 
			
		||||
                      getNumeric = checkIsZeroInput + getNumeric;
 | 
			
		||||
                    }
 | 
			
		||||
                  }else{
 | 
			
		||||
                    getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
 | 
			
		||||
                  }
 | 
			
		||||
                  String formatNumeric = NumberFormatter.numberCurrency(
 | 
			
		||||
                      double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
 | 
			
		||||
                  inputController.text = formatNumeric;
 | 
			
		||||
                }),
 | 
			
		||||
                SizedBox(height: 8),
 | 
			
		||||
                ButtonView(
 | 
			
		||||
                  name: 'Next',
 | 
			
		||||
                  onPressed: () {
 | 
			
		||||
                    widget.nextMove(inputController.text);
 | 
			
		||||
                  },
 | 
			
		||||
                  width: SizeConfig.width,
 | 
			
		||||
                  heightWrapContent: true,
 | 
			
		||||
                  contentPadding: EdgeInsets.symmetric(vertical: 16),
 | 
			
		||||
                  marginVertical: 0,
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										182
									
								
								lib/application/component/subscribe/other_plan_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,182 @@
 | 
			
		||||
import 'package:cims_apps/application/assets/path_assets.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/image/image_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class Plan {
 | 
			
		||||
  String img, name;
 | 
			
		||||
 | 
			
		||||
  Plan(this.img, this.name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class OtherPlanView extends StatefulWidget {
 | 
			
		||||
  final void Function(String value) selectedPlan;
 | 
			
		||||
  const OtherPlanView({super.key, required this.selectedPlan});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<OtherPlanView> createState() => _OtherPlanViewState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _OtherPlanViewState extends State<OtherPlanView> {
 | 
			
		||||
  TextEditingController createController = TextEditingController();
 | 
			
		||||
  Plan selectedPlan = Plan('', '');
 | 
			
		||||
 | 
			
		||||
  List<Plan> listPlan = [
 | 
			
		||||
    Plan(PathAssets.iconToga, 'Education'),
 | 
			
		||||
    Plan(PathAssets.iconCake, 'Marriage'),
 | 
			
		||||
    Plan(PathAssets.iconHouse, 'Home'),
 | 
			
		||||
    Plan(PathAssets.iconTicket, 'Entertainment'),
 | 
			
		||||
    Plan(PathAssets.iconGadget, 'Gadget'),
 | 
			
		||||
    Plan(PathAssets.iconMarket, 'Business'),
 | 
			
		||||
    Plan(PathAssets.iconBag, 'Fashion'),
 | 
			
		||||
    Plan(PathAssets.iconCart, 'Shop'),
 | 
			
		||||
    Plan(PathAssets.iconCar, 'Vehicle'),
 | 
			
		||||
    Plan(PathAssets.iconPlane, 'Holiday'),
 | 
			
		||||
    Plan(PathAssets.iconCreatePlan, 'Create Plan'),
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    // TODO: implement dispose
 | 
			
		||||
    super.dispose();
 | 
			
		||||
    createController.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: CustomAppBar(
 | 
			
		||||
        height: 70,
 | 
			
		||||
        title: 'Other Plan'
 | 
			
		||||
      ),
 | 
			
		||||
      body: GridView(
 | 
			
		||||
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 32),
 | 
			
		||||
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
 | 
			
		||||
        children: listPlan.map((e) => cardPlan(e)).toList(),
 | 
			
		||||
      ),
 | 
			
		||||
      bottomNavigationBar: Container(
 | 
			
		||||
        height: 110,
 | 
			
		||||
        padding: EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
        child: ButtonView(
 | 
			
		||||
          name: 'Select',
 | 
			
		||||
          disabled: !(selectedPlan.img != ''),
 | 
			
		||||
          onPressed: () {
 | 
			
		||||
            Navigator.pop(context);
 | 
			
		||||
            widget.selectedPlan(selectedPlan.name);
 | 
			
		||||
          },
 | 
			
		||||
          heightWrapContent: true,
 | 
			
		||||
          width: SizeConfig.width,
 | 
			
		||||
          contentPadding: EdgeInsets.symmetric(vertical: 12),
 | 
			
		||||
          textColor: selectedPlan.img == '' ? ColorPalette.slate500 : ColorPalette.white,
 | 
			
		||||
          disabledBgColor: ColorPalette.slate200,
 | 
			
		||||
          backgroundColor: ColorPalette.primary,
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget cardPlan(Plan plan) {
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: () {
 | 
			
		||||
        if(plan.name == 'Create Plan'){
 | 
			
		||||
          showModalBottomSheet(
 | 
			
		||||
            context: context,
 | 
			
		||||
            builder: (context) => modalCreatePlan(),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        setState(() {
 | 
			
		||||
          selectedPlan = plan;
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      child: Container(
 | 
			
		||||
        padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
 | 
			
		||||
        decoration: BoxDecoration(
 | 
			
		||||
          borderRadius: BorderRadius.circular(16),
 | 
			
		||||
          border: Border.all(color: selectedPlan == plan ? ColorPalette.primary : Colors.transparent)
 | 
			
		||||
        ),
 | 
			
		||||
        child: Column(
 | 
			
		||||
          mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
          children: [
 | 
			
		||||
            Container(
 | 
			
		||||
              width: SizeConfig.width * 0.12,
 | 
			
		||||
              height: SizeConfig.width * 0.12,
 | 
			
		||||
              padding: EdgeInsets.all(12),
 | 
			
		||||
              alignment: Alignment.center,
 | 
			
		||||
              decoration: BoxDecoration(
 | 
			
		||||
                borderRadius: BorderRadius.circular(8),
 | 
			
		||||
                color: ColorPalette.blue200.withOpacity(0.5)
 | 
			
		||||
              ),
 | 
			
		||||
              child: ImageView(image: plan.img)
 | 
			
		||||
            ),
 | 
			
		||||
            SizedBox(height: 12),
 | 
			
		||||
            Text(plan.name,
 | 
			
		||||
              style: TextStyle(
 | 
			
		||||
                color: selectedPlan == plan ? ColorPalette.primary : ColorPalette.slate800,
 | 
			
		||||
                fontWeight: FontWeight.w600
 | 
			
		||||
              ),
 | 
			
		||||
            )
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget modalCreatePlan() {
 | 
			
		||||
    return Container(
 | 
			
		||||
      padding: EdgeInsets.all(24),
 | 
			
		||||
      child: Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        children: [
 | 
			
		||||
          Row(
 | 
			
		||||
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
            children: [
 | 
			
		||||
              Text('Create your plan',
 | 
			
		||||
                style: TextStyle(
 | 
			
		||||
                  fontWeight: FontWeight.w600,
 | 
			
		||||
                  color: ColorPalette.slate800,
 | 
			
		||||
                  fontSize: 16
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              GestureDetector(
 | 
			
		||||
                onTap: () {
 | 
			
		||||
                  Navigator.pop(context);
 | 
			
		||||
                },
 | 
			
		||||
                child: Icon(Icons.close_rounded),
 | 
			
		||||
              )
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
          TextFormView(
 | 
			
		||||
            name: 'Objective Name',
 | 
			
		||||
            ctrl: createController,
 | 
			
		||||
          ),
 | 
			
		||||
          SizedBox(height: 24),
 | 
			
		||||
          ButtonView(
 | 
			
		||||
            name: 'Select',
 | 
			
		||||
            marginVertical: 0,
 | 
			
		||||
            disabled: !(createController.text != ''),
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              Navigator.of(context)..pop()..pop();
 | 
			
		||||
              widget.selectedPlan(selectedPlan.name);
 | 
			
		||||
            },
 | 
			
		||||
            heightWrapContent: true,
 | 
			
		||||
            width: SizeConfig.width,
 | 
			
		||||
            contentPadding: EdgeInsets.symmetric(vertical: 16),
 | 
			
		||||
            textColor: createController.text == '' ? ColorPalette.slate500 : ColorPalette.white,
 | 
			
		||||
            disabledBgColor: ColorPalette.slate200,
 | 
			
		||||
            backgroundColor: ColorPalette.primary,
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +1,33 @@
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/route/route.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/number_formatter.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/step_subscribe/payment_method_view.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
class TotalPaymentView extends StatefulWidget {
 | 
			
		||||
  final int totalInvest;
 | 
			
		||||
  final List<Product> listProduct;
 | 
			
		||||
  const ResultTotalProduct({super.key, required this.listProduct, required this.totalInvest});
 | 
			
		||||
  const TotalPaymentView({
 | 
			
		||||
    super.key,
 | 
			
		||||
    required this.listProduct,
 | 
			
		||||
    required this.totalInvest,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<TotalPaymentView> createState() => _TotalPaymentViewState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _TotalPaymentViewState extends State<TotalPaymentView> {
 | 
			
		||||
  bool isAgreement = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
 | 
			
		||||
    return Container(
 | 
			
		||||
      decoration: BoxDecoration(
 | 
			
		||||
        color: Colors.white,
 | 
			
		||||
        borderRadius: BorderRadius.circular(16)
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          borderRadius: BorderRadius.circular(16)
 | 
			
		||||
      ),
 | 
			
		||||
      child: Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
@@ -25,7 +37,7 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                Text('Your Investment Today',
 | 
			
		||||
                const Text('Your Investment Today',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.slate800,
 | 
			
		||||
                      fontWeight: FontWeight.w600,
 | 
			
		||||
@@ -33,92 +45,92 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                GestureDetector(
 | 
			
		||||
                  onTap: () => Navigator.pop(context),
 | 
			
		||||
                  child: Icon(Icons.close_rounded)
 | 
			
		||||
                    onTap: () => Navigator.pop(context),
 | 
			
		||||
                    child: const Icon(Icons.close_rounded)
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          ...listProduct.asMap().entries.map((e) {
 | 
			
		||||
          ...widget.listProduct.asMap().entries.map((e) {
 | 
			
		||||
            return Container(
 | 
			
		||||
              padding: EdgeInsets.only(left: 16, right: 24, bottom: 16, top: 16),
 | 
			
		||||
              padding: const EdgeInsets.only(left: 16, right: 24, bottom: 16, top: 16),
 | 
			
		||||
              decoration: BoxDecoration(
 | 
			
		||||
                border: Border(
 | 
			
		||||
                  left: BorderSide(
 | 
			
		||||
                    color: ColorPalette.investTypeColor[e.value.type]!,
 | 
			
		||||
                    width: 8,
 | 
			
		||||
                  border: Border(
 | 
			
		||||
                      left: BorderSide(
 | 
			
		||||
                        width: 8,
 | 
			
		||||
                        color: ColorPalette.investTypeColor[e.value.type]!
 | 
			
		||||
                      )
 | 
			
		||||
                  )
 | 
			
		||||
                )
 | 
			
		||||
              ),
 | 
			
		||||
              child: Row(
 | 
			
		||||
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                children: [
 | 
			
		||||
                  Expanded(
 | 
			
		||||
                    flex: 5,
 | 
			
		||||
                    child: Text(e.value.name,
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        color: ColorPalette.slate400,
 | 
			
		||||
                        fontWeight: FontWeight.w600,
 | 
			
		||||
                        fontSize: 16
 | 
			
		||||
                      ),
 | 
			
		||||
                    )
 | 
			
		||||
                      flex: 5,
 | 
			
		||||
                      child: Text(e.value.name ?? '',
 | 
			
		||||
                        style: const TextStyle(
 | 
			
		||||
                            color: ColorPalette.slate400,
 | 
			
		||||
                            fontWeight: FontWeight.w600,
 | 
			
		||||
                            fontSize: 16
 | 
			
		||||
                        ),
 | 
			
		||||
                      )
 | 
			
		||||
                  ),
 | 
			
		||||
                  Expanded(
 | 
			
		||||
                    flex: 7,
 | 
			
		||||
                    child: Text(
 | 
			
		||||
                      NumberFormatter.numberCurrency(totalInvest / e.value.totalPercent, 'Rp ', 'id_ID'),
 | 
			
		||||
                      textAlign: TextAlign.end,
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        fontWeight: FontWeight.w700,
 | 
			
		||||
                        fontSize: 18,
 | 
			
		||||
                        color: ColorPalette.slate800
 | 
			
		||||
                      ),
 | 
			
		||||
                    )
 | 
			
		||||
                      flex: 7,
 | 
			
		||||
                      child: Text(
 | 
			
		||||
                        NumberFormatter.numberCurrency(widget.totalInvest * e.value.totalPercent!, 'Rp ', 'id_ID'),
 | 
			
		||||
                        textAlign: TextAlign.end,
 | 
			
		||||
                        style: const TextStyle(
 | 
			
		||||
                            fontWeight: FontWeight.w700,
 | 
			
		||||
                            fontSize: 18,
 | 
			
		||||
                            color: ColorPalette.slate800
 | 
			
		||||
                        ),
 | 
			
		||||
                      )
 | 
			
		||||
                  )
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            );
 | 
			
		||||
          }).toList(),
 | 
			
		||||
          SizedBox(height: 16),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
          const SizedBox(height: 16),
 | 
			
		||||
          const Padding(
 | 
			
		||||
            padding: EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                Text('Purchase Commission',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    color: ColorPalette.slate400,
 | 
			
		||||
                    fontWeight: FontWeight.w600,
 | 
			
		||||
                    fontSize: 16
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Text('Free',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    color: ColorPalette.primary,
 | 
			
		||||
                    fontSize: 18,
 | 
			
		||||
                    fontWeight: FontWeight.w700
 | 
			
		||||
                  ),
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          SizedBox(height: 16,),
 | 
			
		||||
          Container(
 | 
			
		||||
            color: ColorPalette.slate200.withOpacity(0.5),
 | 
			
		||||
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                Text('Total',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.slate400,
 | 
			
		||||
                      fontWeight: FontWeight.w600,
 | 
			
		||||
                      fontSize: 16
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Text(NumberFormatter.numberCurrency(totalInvest, 'Rp ', 'id_ID'),
 | 
			
		||||
                  textAlign: TextAlign.end,
 | 
			
		||||
                Text('Free',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.primary,
 | 
			
		||||
                      fontSize: 18,
 | 
			
		||||
                      fontWeight: FontWeight.w700
 | 
			
		||||
                  ),
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          const SizedBox(height: 16,),
 | 
			
		||||
          Container(
 | 
			
		||||
            color: ColorPalette.slate200.withOpacity(0.5),
 | 
			
		||||
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                const Text('Total',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.slate400,
 | 
			
		||||
                      fontWeight: FontWeight.w600,
 | 
			
		||||
                      fontSize: 16
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'),
 | 
			
		||||
                  textAlign: TextAlign.end,
 | 
			
		||||
                  style: const TextStyle(
 | 
			
		||||
                      fontWeight: FontWeight.w700,
 | 
			
		||||
                      fontSize: 18,
 | 
			
		||||
                      color: ColorPalette.slate800
 | 
			
		||||
@@ -133,16 +145,16 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                Text('Total Payment',
 | 
			
		||||
                const Text('Total Payment',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                      color: ColorPalette.slate400,
 | 
			
		||||
                      fontWeight: FontWeight.w600,
 | 
			
		||||
                      fontSize: 16
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Text(NumberFormatter.numberCurrency(totalInvest, 'Rp ', 'id_ID'),
 | 
			
		||||
                Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'),
 | 
			
		||||
                  textAlign: TextAlign.end,
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                  style: const TextStyle(
 | 
			
		||||
                      fontWeight: FontWeight.w700,
 | 
			
		||||
                      fontSize: 18,
 | 
			
		||||
                      color: ColorPalette.slate800
 | 
			
		||||
@@ -152,13 +164,15 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          ButtonView(
 | 
			
		||||
            disabled: true,
 | 
			
		||||
            disabled: !isAgreement,
 | 
			
		||||
            name: 'Subscribe Now',
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
 | 
			
		||||
              routePush(context, page: PaymentMethodView(
 | 
			
		||||
                totalInvest: widget.totalInvest,
 | 
			
		||||
              ));
 | 
			
		||||
            },
 | 
			
		||||
            disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
 | 
			
		||||
            textColor: ColorPalette.slate400,
 | 
			
		||||
            textColor: isAgreement ? Colors.white : ColorPalette.slate400,
 | 
			
		||||
            textWeight: FontWeight.w700,
 | 
			
		||||
            textSize: 20,
 | 
			
		||||
            backgroundColor: ColorPalette.primary,
 | 
			
		||||
@@ -169,29 +183,48 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget buttonAgreement() {
 | 
			
		||||
    bool isAgree = isAgreement;
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
 | 
			
		||||
      child: Row(
 | 
			
		||||
        crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
        children: [
 | 
			
		||||
          SizedBox(
 | 
			
		||||
            height: 24,
 | 
			
		||||
            width: 24,
 | 
			
		||||
            child: Radio(
 | 
			
		||||
              value: false,
 | 
			
		||||
              groupValue: false,
 | 
			
		||||
              onChanged: (value) {
 | 
			
		||||
 | 
			
		||||
              },
 | 
			
		||||
              activeColor: ColorPalette.primary,
 | 
			
		||||
          GestureDetector(
 | 
			
		||||
            onTap: () {
 | 
			
		||||
              setState(() {
 | 
			
		||||
                isAgreement = !isAgreement;
 | 
			
		||||
              });
 | 
			
		||||
            },
 | 
			
		||||
            child: AnimatedContainer(
 | 
			
		||||
              margin: const EdgeInsets.only(top: 4),
 | 
			
		||||
              duration: const Duration(milliseconds: 200),
 | 
			
		||||
              height: 16,
 | 
			
		||||
              width: 16,
 | 
			
		||||
              padding: const EdgeInsets.all(1),
 | 
			
		||||
              alignment: Alignment.center,
 | 
			
		||||
              decoration: BoxDecoration(
 | 
			
		||||
                  shape: BoxShape.circle,
 | 
			
		||||
                  border: Border.all(
 | 
			
		||||
                      color: isAgree ? ColorPalette.primary : ColorPalette.slate200
 | 
			
		||||
                  )
 | 
			
		||||
              ),
 | 
			
		||||
              child: AnimatedContainer(
 | 
			
		||||
                duration: const Duration(milliseconds: 200),
 | 
			
		||||
                child: Container(
 | 
			
		||||
                  decoration: BoxDecoration(
 | 
			
		||||
                      color: isAgree ? ColorPalette.primary : ColorPalette.white,
 | 
			
		||||
                      shape: BoxShape.circle
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          SizedBox(width: 12,),
 | 
			
		||||
          const SizedBox(width: 12,),
 | 
			
		||||
          Expanded(
 | 
			
		||||
              child: Column(
 | 
			
		||||
                crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                children: [
 | 
			
		||||
                  Text('I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
 | 
			
		||||
                  const Text('I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
 | 
			
		||||
                    style: TextStyle(
 | 
			
		||||
                        fontSize: 16,
 | 
			
		||||
                        fontWeight: FontWeight.w600,
 | 
			
		||||
@@ -202,7 +235,7 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
                      onTap: () {
 | 
			
		||||
 | 
			
		||||
                      },
 | 
			
		||||
                      child: Text('Read More',
 | 
			
		||||
                      child: const Text('Read More',
 | 
			
		||||
                        style: TextStyle(
 | 
			
		||||
                            fontSize: 16,
 | 
			
		||||
                            fontWeight: FontWeight.w600,
 | 
			
		||||
@@ -218,4 +251,4 @@ class ResultTotalProduct extends StatelessWidget {
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								lib/application/component/success_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,52 @@
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/image/image_view.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class SuccessView extends StatelessWidget {
 | 
			
		||||
  final String img;
 | 
			
		||||
  final String textTitle;
 | 
			
		||||
  final Widget? subtitle;
 | 
			
		||||
  final void Function() nextRoute;
 | 
			
		||||
  const SuccessView({super.key,
 | 
			
		||||
    required this.img,
 | 
			
		||||
    required this.textTitle,
 | 
			
		||||
    required this.subtitle,
 | 
			
		||||
    required this.nextRoute
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: Column(
 | 
			
		||||
          mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
          children: [
 | 
			
		||||
            ImageView(image: img, width: SizeConfig.width * .8,),
 | 
			
		||||
            Text(textTitle,
 | 
			
		||||
              style: TextStyle(
 | 
			
		||||
                fontWeight: FontWeight.w700,
 | 
			
		||||
                fontSize: 28,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
            subtitle ?? SizedBox()
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      bottomNavigationBar: Container(
 | 
			
		||||
        padding: EdgeInsets.all(24),
 | 
			
		||||
        height: 110,
 | 
			
		||||
        width: SizeConfig.width,
 | 
			
		||||
        child: ButtonView(
 | 
			
		||||
          name: 'Done',
 | 
			
		||||
          onPressed: nextRoute,
 | 
			
		||||
          marginVertical: 0,
 | 
			
		||||
          heightWrapContent: true,
 | 
			
		||||
          width: SizeConfig.width,
 | 
			
		||||
          textSize: 20,
 | 
			
		||||
          contentPadding: EdgeInsets.symmetric(vertical: 12),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,6 +5,7 @@ import 'package:remove_emoji_input_formatter/remove_emoji_input_formatter.dart';
 | 
			
		||||
 | 
			
		||||
class TextFormView extends StatelessWidget {
 | 
			
		||||
  final String name;
 | 
			
		||||
  final double nameSize;
 | 
			
		||||
  final String? helperText;
 | 
			
		||||
  final String? initialValue;
 | 
			
		||||
  final VoidCallback? onTap;
 | 
			
		||||
@@ -40,6 +41,7 @@ class TextFormView extends StatelessWidget {
 | 
			
		||||
  TextFormView(
 | 
			
		||||
      {Key? key,
 | 
			
		||||
      required this.name,
 | 
			
		||||
      this.nameSize = 16,
 | 
			
		||||
      this.helperText,
 | 
			
		||||
      this.onTap,
 | 
			
		||||
      this.fontColorDisabled,
 | 
			
		||||
@@ -97,17 +99,17 @@ class TextFormView extends StatelessWidget {
 | 
			
		||||
                      children: [
 | 
			
		||||
                        Text(
 | 
			
		||||
                          name,
 | 
			
		||||
                          style: const TextStyle(
 | 
			
		||||
                            fontSize: 16,
 | 
			
		||||
                          style: TextStyle(
 | 
			
		||||
                            fontSize: nameSize,
 | 
			
		||||
                            fontWeight: FontWeight.w600,
 | 
			
		||||
                            color: ColorPalette.slate800,
 | 
			
		||||
                          ),
 | 
			
		||||
                        ),
 | 
			
		||||
                        suffixLable ??
 | 
			
		||||
                            const Text(
 | 
			
		||||
                            Text(
 | 
			
		||||
                              "",
 | 
			
		||||
                              style: TextStyle(
 | 
			
		||||
                                fontSize: 16,
 | 
			
		||||
                                fontSize: nameSize,
 | 
			
		||||
                                color: Colors.red,
 | 
			
		||||
                              ),
 | 
			
		||||
                            ),
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,7 @@ class ColorPalette {
 | 
			
		||||
  static const Color backgroundBlueLight = Color(0xFFEBF3FD);
 | 
			
		||||
  static const Color blue50 = Color(0xFFEFF6FF);
 | 
			
		||||
  static const Color blue200 = Color(0xFFBFDBFE);
 | 
			
		||||
  static const Color blue900 = Color(0xFF1E3A8A);
 | 
			
		||||
  static const Color slate50 = Color(0xFFF8FAFC);
 | 
			
		||||
  static const Color slate200 = Color(0xFFE2E8F0);
 | 
			
		||||
  static const Color slate300 = Color(0xFFCBD5E1);
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ class PasswordView extends StatelessWidget {
 | 
			
		||||
                name: 'Confirm',
 | 
			
		||||
                heightWrapContent: true,
 | 
			
		||||
                width: SizeConfig.width,
 | 
			
		||||
                textSize: 18,
 | 
			
		||||
                marginVertical: 0,
 | 
			
		||||
                contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
 | 
			
		||||
                onPressed: nextStep,
 | 
			
		||||
 
 | 
			
		||||
@@ -50,28 +50,25 @@ class _BottomNavigationViewState extends State<BottomNavigationView> {
 | 
			
		||||
      ),
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return ChangeNotifierProvider(
 | 
			
		||||
      create: (context) => PlanViewModel(),
 | 
			
		||||
      child: Scaffold(
 | 
			
		||||
        body: listWidget[_selectedIndex],
 | 
			
		||||
        bottomNavigationBar: Padding(
 | 
			
		||||
          padding: const EdgeInsets.symmetric(vertical: 12),
 | 
			
		||||
          child: BottomNavigationBar(
 | 
			
		||||
            elevation: 0,
 | 
			
		||||
            onTap: (value) {
 | 
			
		||||
              setState(() {
 | 
			
		||||
                _selectedIndex = value;
 | 
			
		||||
              });
 | 
			
		||||
            },
 | 
			
		||||
            currentIndex: _selectedIndex,
 | 
			
		||||
            items: listNavigation,
 | 
			
		||||
            type: BottomNavigationBarType.fixed,
 | 
			
		||||
            showUnselectedLabels: true,
 | 
			
		||||
            selectedItemColor: ColorPalette.primary,
 | 
			
		||||
            unselectedItemColor: Colors.black,
 | 
			
		||||
            selectedLabelStyle: const TextStyle(color: ColorPalette.primary),
 | 
			
		||||
            unselectedLabelStyle: const TextStyle(color: Colors.black),
 | 
			
		||||
          ),
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      body: listWidget[_selectedIndex],
 | 
			
		||||
      bottomNavigationBar: Padding(
 | 
			
		||||
        padding: const EdgeInsets.symmetric(vertical: 12),
 | 
			
		||||
        child: BottomNavigationBar(
 | 
			
		||||
          elevation: 0,
 | 
			
		||||
          onTap: (value) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              _selectedIndex = value;
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
          currentIndex: _selectedIndex,
 | 
			
		||||
          items: listNavigation,
 | 
			
		||||
          type: BottomNavigationBarType.fixed,
 | 
			
		||||
          showUnselectedLabels: true,
 | 
			
		||||
          selectedItemColor: ColorPalette.primary,
 | 
			
		||||
          unselectedItemColor: Colors.black,
 | 
			
		||||
          selectedLabelStyle: const TextStyle(color: ColorPalette.primary),
 | 
			
		||||
          unselectedLabelStyle: const TextStyle(color: Colors.black),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 
 | 
			
		||||
@@ -228,7 +228,7 @@ class _HomeViewState extends State<HomeView> {
 | 
			
		||||
        children: listPortofolioType.asMap().entries.map((e) {
 | 
			
		||||
          return  GestureDetector(
 | 
			
		||||
            onTap: () {
 | 
			
		||||
              routePush(context, page: InvestTypeView(e.value.name));
 | 
			
		||||
              routePush(context, page: InvestTypeView(title: e.value.name));
 | 
			
		||||
            },
 | 
			
		||||
            child: Container(
 | 
			
		||||
              color: Colors.white,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,21 +6,14 @@ import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/route/route.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/number_formatter.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/product_view.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_view.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class Product {
 | 
			
		||||
  String name;
 | 
			
		||||
  double yield;
 | 
			
		||||
  double priceUnit;
 | 
			
		||||
  double funds;
 | 
			
		||||
  
 | 
			
		||||
  Product(this.name, this.yield, this.priceUnit, this.funds);
 | 
			
		||||
}
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class InvestTypeView extends StatefulWidget {
 | 
			
		||||
  final String title;
 | 
			
		||||
  const InvestTypeView(this.title, {super.key});
 | 
			
		||||
  const InvestTypeView({super.key, required this.title});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<InvestTypeView> createState() => _InvestTypeViewState();
 | 
			
		||||
@@ -29,71 +22,89 @@ class InvestTypeView extends StatefulWidget {
 | 
			
		||||
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)
 | 
			
		||||
    Product(name: 'Gemilang Dana Kas Maxima', type: '', yield: 8.17, priceUnit: 2600.79, funds: 6300000),
 | 
			
		||||
    Product(name: 'Gemilang Dana Likuid', type: '', yield: 6.42, priceUnit: 1600.79, funds: 2340000),
 | 
			
		||||
    Product(name: 'Gemilang Income Fund', type: '', yield: 8.17, priceUnit: 2600.79, funds: 6300000)
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    super.initState();
 | 
			
		||||
    listProduct = listProduct.map((e) {
 | 
			
		||||
      e.type = widget.title;
 | 
			
		||||
      return e;
 | 
			
		||||
    }).toList();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  @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,
 | 
			
		||||
    return ChangeNotifierProvider<ProductViewModel>(
 | 
			
		||||
      create: (context) => ProductViewModel(),
 | 
			
		||||
      child: Consumer<ProductViewModel>(
 | 
			
		||||
        builder: (context, provider, child) {
 | 
			
		||||
          return Scaffold(
 | 
			
		||||
            body: SizedBox(
 | 
			
		||||
              width: SizeConfig.width,
 | 
			
		||||
              height: SizeConfig.height,
 | 
			
		||||
              child: Stack(
 | 
			
		||||
                children: [
 | 
			
		||||
                  const ImageView(image: PathAssets.imgDashboardAccount),
 | 
			
		||||
                  Column(
 | 
			
		||||
                    children: [
 | 
			
		||||
                      const BackButtonView(),
 | 
			
		||||
                      TextTitle(title: widget.title, color: Colors.white),
 | 
			
		||||
                      SizedBox(
 | 
			
		||||
                        width: SizeConfig.width * 0.1,
 | 
			
		||||
                      )
 | 
			
		||||
                      const SizedBox(
 | 
			
		||||
                        height: 50,
 | 
			
		||||
                      ),
 | 
			
		||||
                      Padding(
 | 
			
		||||
                        padding: const EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
                        child: Row(
 | 
			
		||||
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                          children: [
 | 
			
		||||
                            const BackButtonView(),
 | 
			
		||||
                            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: () {
 | 
			
		||||
                                    provider.setSelectedProduct(e.value);
 | 
			
		||||
                                    routePush(context, page: ProductView(widget.title));
 | 
			
		||||
                                  },
 | 
			
		||||
                                  child: Padding(
 | 
			
		||||
                                    padding: EdgeInsets.only(top: e.key != 0 ? 24 : 0),
 | 
			
		||||
                                    child: cardProduct(e.value),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                );
 | 
			
		||||
                              }).toList(),
 | 
			
		||||
                            )
 | 
			
		||||
                          ],
 | 
			
		||||
                        ),
 | 
			
		||||
                      ),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                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(),
 | 
			
		||||
                      )
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
                  )
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
@@ -158,7 +169,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
 | 
			
		||||
              ),
 | 
			
		||||
              Expanded(
 | 
			
		||||
                child: Text(
 | 
			
		||||
                  product.name,
 | 
			
		||||
                  product.name ?? '',
 | 
			
		||||
                  style: const TextStyle(
 | 
			
		||||
                    fontWeight: FontWeight.bold,
 | 
			
		||||
                    fontSize: 18
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/goal_investing_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/risk_profile.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
 | 
			
		||||
@@ -22,6 +23,13 @@ class PlanView extends StatefulWidget {
 | 
			
		||||
class _PlanViewState extends State<PlanView> {
 | 
			
		||||
  TextEditingController inputController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    inputController.text = 'Rp 0';
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    // TODO: implement dispose
 | 
			
		||||
@@ -103,101 +111,13 @@ class _PlanViewState extends State<PlanView> {
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          Divider(color: ColorPalette.slate200, height: 1),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
 | 
			
		||||
            child: Column(
 | 
			
		||||
              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
              children: [
 | 
			
		||||
                Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Text(text,
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        fontSize: 20,
 | 
			
		||||
                        fontWeight: FontWeight.w700,
 | 
			
		||||
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    Row(
 | 
			
		||||
                      children: [
 | 
			
		||||
                        Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
 | 
			
		||||
                        SizedBox(width: 4),
 | 
			
		||||
                        Text('Change',
 | 
			
		||||
                          style: TextStyle(
 | 
			
		||||
                            fontSize: 16,
 | 
			
		||||
                            fontWeight: FontWeight.w600,
 | 
			
		||||
                            color: ColorPalette.primary
 | 
			
		||||
                          ),
 | 
			
		||||
                        )
 | 
			
		||||
                      ],
 | 
			
		||||
                    )
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                TextField(
 | 
			
		||||
                  controller: inputController,
 | 
			
		||||
                  textAlign: TextAlign.center,
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    fontSize: 28,
 | 
			
		||||
                    fontWeight: FontWeight.w600,
 | 
			
		||||
                    color: ColorPalette.slate800
 | 
			
		||||
                  ),
 | 
			
		||||
                  keyboardType: TextInputType.number,
 | 
			
		||||
                  onChanged: (value) {
 | 
			
		||||
                    value = value.replaceAll('Rp ', '').replaceAll('.', '');
 | 
			
		||||
                    double parseValue = double.parse(value);
 | 
			
		||||
                    if(value.isNotEmpty){
 | 
			
		||||
                      inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
 | 
			
		||||
                    }else{
 | 
			
		||||
                      inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
 | 
			
		||||
                    }
 | 
			
		||||
                  },
 | 
			
		||||
                  decoration: InputDecoration(
 | 
			
		||||
                    enabledBorder: UnderlineInputBorder(
 | 
			
		||||
                      borderSide: BorderSide(
 | 
			
		||||
                        color: ColorPalette.primary,
 | 
			
		||||
                        width: 2
 | 
			
		||||
                      ),
 | 
			
		||||
                    )
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                SizedBox(height: 12),
 | 
			
		||||
                Text('Minimum Budget Rp1,000,000',
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    color: ColorPalette.slate400,
 | 
			
		||||
                    fontSize: 16,
 | 
			
		||||
                    fontWeight: FontWeight.w600
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                SizedBox(height: 16),
 | 
			
		||||
                NumericPad(onNumberSelected: (p0) {
 | 
			
		||||
                  String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', '');
 | 
			
		||||
                  String getNumeric = p0;
 | 
			
		||||
                  if(p0.isNotEmpty){
 | 
			
		||||
                    if(checkIsZeroInput != '0'){
 | 
			
		||||
                      getNumeric = checkIsZeroInput + getNumeric;
 | 
			
		||||
                    }
 | 
			
		||||
                  }else{
 | 
			
		||||
                    getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
 | 
			
		||||
                  }
 | 
			
		||||
                  String formatNumeric = NumberFormatter.numberCurrency(
 | 
			
		||||
                      double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
 | 
			
		||||
                  inputController.text = formatNumeric;
 | 
			
		||||
                }),
 | 
			
		||||
                SizedBox(height: 8),
 | 
			
		||||
                ButtonView(
 | 
			
		||||
                  name: 'Next',
 | 
			
		||||
                  onPressed: () {
 | 
			
		||||
                    Navigator.pop(context);
 | 
			
		||||
                    int formatIntParse = int.parse(inputController.text.replaceAll('Rp ', '').replaceAll(',', ''));
 | 
			
		||||
                    showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
 | 
			
		||||
                  },
 | 
			
		||||
                  width: SizeConfig.width,
 | 
			
		||||
                  heightWrapContent: true,
 | 
			
		||||
                  contentPadding: EdgeInsets.symmetric(vertical: 16),
 | 
			
		||||
                  marginVertical: 0,
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          InputInvestmentView(
 | 
			
		||||
            selectedPlan: text,
 | 
			
		||||
            nextMove: (value) {
 | 
			
		||||
              Navigator.pop(context);
 | 
			
		||||
              int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
 | 
			
		||||
              showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,12 @@
 | 
			
		||||
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/subscribe/total_payment_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/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_total_product.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class Product {
 | 
			
		||||
  String name, type;
 | 
			
		||||
  double totalPercent;
 | 
			
		||||
 | 
			
		||||
  Product(this.name, this.type, this.totalPercent);
 | 
			
		||||
}
 | 
			
		||||
class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
  final int totalInvest;
 | 
			
		||||
  const ResultOptionsProduct({super.key, required this.totalInvest});
 | 
			
		||||
@@ -19,9 +14,9 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    List<Product> listProduct = [
 | 
			
		||||
      Product('Gemilang Dana Kas Maxima', 'Money Market', 0.7),
 | 
			
		||||
      Product('Gemilang Dana Likuid', 'Bonds', 0.2),
 | 
			
		||||
      Product('Gemilang Kas 2 Kelas A', 'Shares', 0.1)
 | 
			
		||||
      Product(name: 'Gemilang Dana Kas Maxima', type: 'Money Market', totalPercent: 0.7),
 | 
			
		||||
      Product(name: 'Gemilang Dana Likuid', type: 'Bonds', totalPercent: 0.2),
 | 
			
		||||
      Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1)
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return Container(
 | 
			
		||||
@@ -44,7 +39,7 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
                  color: ColorPalette.slate800
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              const Icon(Icons.close_rounded, color: ColorPalette.slate400)
 | 
			
		||||
              Icon(Icons.close_rounded, color: ColorPalette.slate400)
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
          const SizedBox(height: 32),
 | 
			
		||||
@@ -58,8 +53,8 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
                      color: Colors.white,
 | 
			
		||||
                      border: Border.all(color: ColorPalette.slate200),
 | 
			
		||||
                      borderRadius: BorderRadius.circular(12),
 | 
			
		||||
                      boxShadow: [
 | 
			
		||||
                        const BoxShadow(
 | 
			
		||||
                      boxShadow: const [
 | 
			
		||||
                        BoxShadow(
 | 
			
		||||
                            color: Color(0XFF1E293B0A)
 | 
			
		||||
                        )
 | 
			
		||||
                      ]
 | 
			
		||||
@@ -76,10 +71,10 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
                            child: Column(
 | 
			
		||||
                              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Text(e.value.name,
 | 
			
		||||
                                Text(e.value.name ?? '',
 | 
			
		||||
                                  style: const TextStyle(
 | 
			
		||||
                                      fontWeight: FontWeight.w700,
 | 
			
		||||
                                      color: ColorPalette.slate800
 | 
			
		||||
                                    fontWeight: FontWeight.w700,
 | 
			
		||||
                                    color: ColorPalette.slate800,
 | 
			
		||||
                                  ),
 | 
			
		||||
                                ),
 | 
			
		||||
                                const SizedBox(height: 4,),
 | 
			
		||||
@@ -90,17 +85,18 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
                                      color: ColorPalette.investTypeBgColor[e.value.type],
 | 
			
		||||
                                      borderRadius: BorderRadius.circular(40)
 | 
			
		||||
                                  ),
 | 
			
		||||
                                  child: Text(e.value.type,
 | 
			
		||||
                                  child: Text(e.value.type ?? '',
 | 
			
		||||
                                    style: TextStyle(
 | 
			
		||||
                                        color: ColorPalette.investTypeColor[e.value.type],
 | 
			
		||||
                                        fontWeight: FontWeight.w600
 | 
			
		||||
                                      color: ColorPalette.investTypeColor[e.value.type],
 | 
			
		||||
                                      fontWeight: FontWeight.w600,
 | 
			
		||||
                                      fontSize: 12
 | 
			
		||||
                                    ),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                )
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                          ),
 | 
			
		||||
                          Text('${(e.value.totalPercent * 100).toInt()} %',
 | 
			
		||||
                          Text('${(e.value.totalPercent! * 100).toInt()} %',
 | 
			
		||||
                            style: const TextStyle(
 | 
			
		||||
                                fontWeight: FontWeight.w700,
 | 
			
		||||
                                fontSize: 16,
 | 
			
		||||
@@ -135,11 +131,14 @@ class ResultOptionsProduct extends StatelessWidget {
 | 
			
		||||
          ButtonView(
 | 
			
		||||
            name: 'Next',
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              Navigator.pop(context);
 | 
			
		||||
              showModalBottomSheet(
 | 
			
		||||
                  context: context,
 | 
			
		||||
                  isScrollControlled: true,
 | 
			
		||||
                  builder: (context) => ResultTotalProduct(listProduct: listProduct, totalInvest: totalInvest)
 | 
			
		||||
                  builder: (context) =>
 | 
			
		||||
                    TotalPaymentView(
 | 
			
		||||
                      listProduct: listProduct,
 | 
			
		||||
                      totalInvest: totalInvest,
 | 
			
		||||
                    )
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
            width: SizeConfig.width,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,6 @@
 | 
			
		||||
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class PlanViewModel extends ChangeNotifier {
 | 
			
		||||
  bool isAgreement = false;
 | 
			
		||||
 | 
			
		||||
  void setAgreement() {
 | 
			
		||||
    isAgreement = !isAgreement;
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
  List<Product> listProduct = [];
 | 
			
		||||
}
 | 
			
		||||
@@ -9,9 +9,12 @@ import 'package:cims_apps/application/component/text_title/text_title.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/number_formatter.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/product_chart_view.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_chart_view.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:group_button/group_button.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class Time {
 | 
			
		||||
  int value;
 | 
			
		||||
@@ -97,58 +100,65 @@ class _ProductViewState extends State<ProductView> {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      body: SizedBox(
 | 
			
		||||
        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: [
 | 
			
		||||
                      BackButtonView(),
 | 
			
		||||
                      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)
 | 
			
		||||
                        ],
 | 
			
		||||
                      )
 | 
			
		||||
                    ],
 | 
			
		||||
    return ChangeNotifierProvider(
 | 
			
		||||
      create: (context) => ProductViewModel(),
 | 
			
		||||
      child: Scaffold(
 | 
			
		||||
        body: SizedBox(
 | 
			
		||||
          child: Stack(
 | 
			
		||||
            children: [
 | 
			
		||||
              const ImageView(image: PathAssets.imgDashboardAccount),
 | 
			
		||||
              Column(
 | 
			
		||||
                children: [
 | 
			
		||||
                  const SizedBox(
 | 
			
		||||
                    height: 50,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                const SizedBox(
 | 
			
		||||
                  height: 24,
 | 
			
		||||
                ),
 | 
			
		||||
                headContainer(),
 | 
			
		||||
                const SizedBox(
 | 
			
		||||
                  height: 24,
 | 
			
		||||
                ),
 | 
			
		||||
                Expanded(
 | 
			
		||||
                  child: contentContainer()
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          ],
 | 
			
		||||
                  const Padding(
 | 
			
		||||
                    padding: EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
                    child: Row(
 | 
			
		||||
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                      children: [
 | 
			
		||||
                        BackButtonView(),
 | 
			
		||||
                        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()
 | 
			
		||||
                  )
 | 
			
		||||
                ],
 | 
			
		||||
              )
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      bottomNavigationBar: Container(
 | 
			
		||||
        height: SizeConfig.height * .1,
 | 
			
		||||
        padding: const EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
        child: ButtonView(
 | 
			
		||||
          name: 'Buy',
 | 
			
		||||
          onPressed: () {
 | 
			
		||||
 | 
			
		||||
          },
 | 
			
		||||
          height: SizeConfig.height * 0.06,
 | 
			
		||||
          marginVertical: 16,
 | 
			
		||||
        bottomNavigationBar: Container(
 | 
			
		||||
          height: SizeConfig.height * .1,
 | 
			
		||||
          padding: const EdgeInsets.symmetric(horizontal: 24),
 | 
			
		||||
          child: ButtonView(
 | 
			
		||||
            name: 'Subscribe',
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              showModalBottomSheet(
 | 
			
		||||
                context: context,
 | 
			
		||||
                isScrollControlled: true,
 | 
			
		||||
                builder: (context) => SelectGoalInvesting(),
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
            height: SizeConfig.height * 0.06,
 | 
			
		||||
            marginVertical: 16,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
@@ -581,18 +591,10 @@ class _ProductViewState extends State<ProductView> {
 | 
			
		||||
          },
 | 
			
		||||
          selectedMachineType
 | 
			
		||||
        ),
 | 
			
		||||
        const Padding(
 | 
			
		||||
          padding: EdgeInsets.only(top: 16, bottom: 8),
 | 
			
		||||
          child: Text(
 | 
			
		||||
            "Today's Investment Estimated Value",
 | 
			
		||||
            style: TextStyle(
 | 
			
		||||
              fontWeight: FontWeight.w600,
 | 
			
		||||
              color: ColorPalette.slate800
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        SizedBox(height: 16),
 | 
			
		||||
        TextFormView(
 | 
			
		||||
          name: '',
 | 
			
		||||
          name: "Today's Investment Estimated Value",
 | 
			
		||||
          nameSize: 14,
 | 
			
		||||
          ctrl: machineController,
 | 
			
		||||
          keyboardType: TextInputType.number,
 | 
			
		||||
          contentPadding: EdgeInsets.all(12),
 | 
			
		||||
@@ -0,0 +1,282 @@
 | 
			
		||||
import 'dart:ffi';
 | 
			
		||||
 | 
			
		||||
import 'package:cims_apps/application/assets/path_assets.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/button/button_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/modal_redirect_app.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/success_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/core/route/route.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/number_formatter.dart';
 | 
			
		||||
import 'package:cims_apps/core/utils/size_config.dart';
 | 
			
		||||
import 'package:cims_apps/features/bottom_navigation_view.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class Payment {
 | 
			
		||||
  String name;
 | 
			
		||||
  int fee;
 | 
			
		||||
  double? discount;
 | 
			
		||||
 | 
			
		||||
  Payment({required this.name, required this.fee, this.discount = 1});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PaymentMethodView extends StatefulWidget {
 | 
			
		||||
  final int totalInvest;
 | 
			
		||||
  const PaymentMethodView({super.key, required this.totalInvest });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<PaymentMethodView> createState() => _PaymentMethodViewState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _PaymentMethodViewState extends State<PaymentMethodView> {
 | 
			
		||||
  int selectedPayment = 0;
 | 
			
		||||
  Payment currentPayment = Payment(name: 'Wallet Pay', fee: 2500);
 | 
			
		||||
  List<Payment> listInstantPayment = [
 | 
			
		||||
    Payment(name: 'Wallet Pay', fee: 2500),
 | 
			
		||||
    Payment(name: 'Link Start', fee: 2500),
 | 
			
		||||
    Payment(name: 'Shopping Pay', fee: 2500, discount: 0.5),
 | 
			
		||||
    Payment(name: 'Fund', fee: 2500, discount: 0.2)
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  List<Payment> listTransferBank = [
 | 
			
		||||
    Payment(name: 'BCA', fee: 2500),
 | 
			
		||||
    Payment(name: 'Bank Republik Indonesia', fee: 2500)
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: const CustomAppBar(
 | 
			
		||||
        height: 70,
 | 
			
		||||
        title: 'Payment Method'
 | 
			
		||||
      ),
 | 
			
		||||
      body: SingleChildScrollView(
 | 
			
		||||
        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
 | 
			
		||||
        child: Column(
 | 
			
		||||
          children: [
 | 
			
		||||
            segmentTitle(Icons.bolt_rounded, 'Instant Payment'),
 | 
			
		||||
            Wrap(
 | 
			
		||||
              runSpacing: 16,
 | 
			
		||||
              children: listInstantPayment.asMap().entries.map((e) {
 | 
			
		||||
                return cardPayment(e.value, e.key);
 | 
			
		||||
              }).toList(),
 | 
			
		||||
            ),
 | 
			
		||||
            const SizedBox(height: 8),
 | 
			
		||||
            segmentTitle(Icons.account_balance_outlined, 'Transfer Bank'),
 | 
			
		||||
            Wrap(
 | 
			
		||||
              runSpacing: 16,
 | 
			
		||||
              children: listTransferBank.asMap().entries.map((e) {
 | 
			
		||||
                return cardPayment(e.value, e.key + (listInstantPayment.length));
 | 
			
		||||
              }).toList(),
 | 
			
		||||
            ),
 | 
			
		||||
            SizedBox(height: 16,)
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      bottomNavigationBar: Container(
 | 
			
		||||
        padding: const EdgeInsets.all(24),
 | 
			
		||||
        child: segmentBottom(currentPayment)
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget segmentTitle(IconData? icon, String title) {
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: const EdgeInsets.symmetric(vertical: 16),
 | 
			
		||||
      child: Row(
 | 
			
		||||
        children: [
 | 
			
		||||
          Icon(icon, color: ColorPalette.primary),
 | 
			
		||||
          const SizedBox(width: 8),
 | 
			
		||||
          Text(title,
 | 
			
		||||
            style: const TextStyle(
 | 
			
		||||
                color: ColorPalette.slate800,
 | 
			
		||||
                fontWeight: FontWeight.w600,
 | 
			
		||||
                fontSize: 16
 | 
			
		||||
            ),
 | 
			
		||||
          )
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget cardPayment(Payment value, int index) {
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: () {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          selectedPayment = index;
 | 
			
		||||
          currentPayment = value;
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      child: AnimatedContainer(
 | 
			
		||||
        duration: const Duration(milliseconds: 200),
 | 
			
		||||
        padding: const EdgeInsets.all(16),
 | 
			
		||||
        decoration: BoxDecoration(
 | 
			
		||||
          borderRadius: BorderRadius.circular(14),
 | 
			
		||||
          border: Border.all(color: selectedPayment == index ? ColorPalette.primary : ColorPalette.slate200)
 | 
			
		||||
        ),
 | 
			
		||||
        child: Column(
 | 
			
		||||
          children: [
 | 
			
		||||
            Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
              children: [
 | 
			
		||||
                Row(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Column(
 | 
			
		||||
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                      children: [
 | 
			
		||||
                        Text(value.name,
 | 
			
		||||
                          style: const TextStyle(
 | 
			
		||||
                            fontSize: 16
 | 
			
		||||
                          ),
 | 
			
		||||
                        ),
 | 
			
		||||
                        RichText(
 | 
			
		||||
                          text: TextSpan(
 | 
			
		||||
                              text: 'Payment fee ',
 | 
			
		||||
                              style: const TextStyle(
 | 
			
		||||
                                fontFamily: 'Manrope',
 | 
			
		||||
                                color: ColorPalette.slate400,
 | 
			
		||||
                              ),
 | 
			
		||||
                              children: [
 | 
			
		||||
                                TextSpan(
 | 
			
		||||
                                  text: '${NumberFormatter.numberCurrency(value.fee, 'Rp ', 'id_ID', decimalDigits: 0)} ',
 | 
			
		||||
                                  style: TextStyle(
 | 
			
		||||
                                    decoration: value.discount != 1 ? TextDecoration.lineThrough : TextDecoration.none,
 | 
			
		||||
                                    fontFamily: 'Manrope',
 | 
			
		||||
                                    color: ColorPalette.slate400,
 | 
			
		||||
                                  ),
 | 
			
		||||
                                ),
 | 
			
		||||
                                if(value.discount != 1)...[
 | 
			
		||||
                                  TextSpan(
 | 
			
		||||
                                    text: value.discount == 0 ? 'Free' : NumberFormatter.numberCurrency(value.fee * value.discount!, 'Rp ', 'id_ID', decimalDigits: 0),
 | 
			
		||||
                                    style: const TextStyle(
 | 
			
		||||
                                      fontFamily: 'Manrope',
 | 
			
		||||
                                      color: ColorPalette.primary,
 | 
			
		||||
                                    ),
 | 
			
		||||
                                  )
 | 
			
		||||
                                ]
 | 
			
		||||
                              ]
 | 
			
		||||
                          )
 | 
			
		||||
                        )
 | 
			
		||||
                      ],
 | 
			
		||||
                    )
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                AnimatedContainer(
 | 
			
		||||
                  duration: const Duration(milliseconds: 200),
 | 
			
		||||
                  width: 16,
 | 
			
		||||
                  height: 16,
 | 
			
		||||
                  alignment: Alignment.center,
 | 
			
		||||
                  decoration: BoxDecoration(
 | 
			
		||||
                    shape: BoxShape.circle,
 | 
			
		||||
                    color: selectedPayment == index ? ColorPalette.primary : Colors.white,
 | 
			
		||||
                    border: Border.all(color: selectedPayment == index ? ColorPalette.primary : ColorPalette.slate200, width: 1.5)
 | 
			
		||||
                  ),
 | 
			
		||||
                  child: const Icon(Icons.done_rounded, color: Colors.white, size: 12),
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget segmentBottom(Payment currentPayment) {
 | 
			
		||||
    return Column(
 | 
			
		||||
      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
      children: [
 | 
			
		||||
        rowTotal('Total Invest', widget.totalInvest),
 | 
			
		||||
        rowTotal('Payment Fee', (currentPayment.fee * currentPayment.discount!).toInt()),
 | 
			
		||||
        Row(
 | 
			
		||||
          children: [
 | 
			
		||||
            Expanded(child: Divider(color: ColorPalette.slate200, height: 1,)),
 | 
			
		||||
            Icon(Icons.add, size: 10,)
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
        rowTotal('Total Payment', widget.totalInvest + (currentPayment.fee * currentPayment.discount!).toInt()),
 | 
			
		||||
        SizedBox(height: 24),
 | 
			
		||||
        ButtonView(
 | 
			
		||||
          name: 'Buy',
 | 
			
		||||
          textSize: 18,
 | 
			
		||||
          marginVertical: 0,
 | 
			
		||||
          width: SizeConfig.width,
 | 
			
		||||
          heightWrapContent: true,
 | 
			
		||||
          contentPadding: EdgeInsets.symmetric(vertical: 16),
 | 
			
		||||
          onPressed: () {
 | 
			
		||||
            List<String> redirect = ['Shopping Pay'];
 | 
			
		||||
            if(redirect.contains(currentPayment.name)){
 | 
			
		||||
              showModalBottomSheet(
 | 
			
		||||
                context: context,
 | 
			
		||||
                builder: (context) {
 | 
			
		||||
                  return ModalRedirectApp(value: currentPayment.name);
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            routePush(context, page: SuccessView(
 | 
			
		||||
              img: PathAssets.imgPaymentSuccess,
 | 
			
		||||
              textTitle: 'Payment Success!',
 | 
			
		||||
              subtitle: RichText(
 | 
			
		||||
                  text: TextSpan(
 | 
			
		||||
                      text: 'Payment With ',
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                        fontFamily: 'Manrope',
 | 
			
		||||
                        fontWeight: FontWeight.w600,
 | 
			
		||||
                        fontSize: 16,
 | 
			
		||||
                        color: ColorPalette.slate500
 | 
			
		||||
                      ),
 | 
			
		||||
                      children: [
 | 
			
		||||
                        TextSpan(
 | 
			
		||||
                            text: currentPayment.name,
 | 
			
		||||
                            style: TextStyle(
 | 
			
		||||
                              fontFamily: 'Manrope',
 | 
			
		||||
                              fontWeight: FontWeight.w700,
 | 
			
		||||
                              fontSize: 16,
 | 
			
		||||
                              color: ColorPalette.slate800
 | 
			
		||||
                            )
 | 
			
		||||
                        ),
 | 
			
		||||
                        TextSpan(
 | 
			
		||||
                            text: ' successful',
 | 
			
		||||
                            style: TextStyle(
 | 
			
		||||
                              fontFamily: 'Manrope',
 | 
			
		||||
                              fontWeight: FontWeight.w600,
 | 
			
		||||
                              fontSize: 16,
 | 
			
		||||
                              color: ColorPalette.slate500
 | 
			
		||||
                            )
 | 
			
		||||
                        )
 | 
			
		||||
                      ]
 | 
			
		||||
                  )
 | 
			
		||||
              ),
 | 
			
		||||
              nextRoute: () {
 | 
			
		||||
                routePush(context, page: BottomNavigationView(), routeType: RouteType.pushRemove);
 | 
			
		||||
              },
 | 
			
		||||
            ));
 | 
			
		||||
          },
 | 
			
		||||
        )
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget rowTotal(String title, int value) {
 | 
			
		||||
    return Row(
 | 
			
		||||
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
      children: [
 | 
			
		||||
        Text(title,
 | 
			
		||||
          style: const TextStyle(
 | 
			
		||||
            fontWeight: FontWeight.w600,
 | 
			
		||||
            color: ColorPalette.slate500,
 | 
			
		||||
            fontSize: 16
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        Text(NumberFormatter.numberCurrency(value, 'Rp', 'id_ID', decimalDigits: 0),
 | 
			
		||||
          style: const TextStyle(
 | 
			
		||||
            fontWeight: FontWeight.w700,
 | 
			
		||||
            color: ColorPalette.slate800,
 | 
			
		||||
            fontSize: 16
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,83 @@
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
 | 
			
		||||
import 'package:cims_apps/application/theme/color_palette.dart';
 | 
			
		||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class SelectGoalInvesting extends StatelessWidget {
 | 
			
		||||
  const SelectGoalInvesting({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return MultiProvider(
 | 
			
		||||
      providers: [
 | 
			
		||||
        ChangeNotifierProvider(create: (context) => ProductViewModel(),)
 | 
			
		||||
      ],
 | 
			
		||||
      child: Consumer<ProductViewModel>(
 | 
			
		||||
        builder: (context, provider, child) {
 | 
			
		||||
          return Container(
 | 
			
		||||
            decoration: BoxDecoration(
 | 
			
		||||
                borderRadius: BorderRadius.circular(16)
 | 
			
		||||
            ),
 | 
			
		||||
            padding: EdgeInsets.all(24),
 | 
			
		||||
            child: Column(
 | 
			
		||||
              mainAxisSize: MainAxisSize.min,
 | 
			
		||||
              children: [
 | 
			
		||||
                Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Text('Your Goal in Investing',
 | 
			
		||||
                      style: TextStyle(
 | 
			
		||||
                          fontWeight: FontWeight.w700,
 | 
			
		||||
                          color: ColorPalette.slate800,
 | 
			
		||||
                          fontSize: 18
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    GestureDetector(
 | 
			
		||||
                        onTap: () {
 | 
			
		||||
                          Navigator.pop(context);
 | 
			
		||||
                        },
 | 
			
		||||
                        child: Icon(Icons.close_rounded, color: ColorPalette.slate400)
 | 
			
		||||
                    )
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                SizedBox(height: 32),
 | 
			
		||||
                GoalInvestingView(
 | 
			
		||||
                  onListSelected: (p0) {
 | 
			
		||||
                    Navigator.pop(context);
 | 
			
		||||
                    showModalBottomSheet(
 | 
			
		||||
                      context: context,
 | 
			
		||||
                      isScrollControlled: true,
 | 
			
		||||
                      builder: (context) {
 | 
			
		||||
                        return InputInvestmentView(
 | 
			
		||||
                          selectedPlan: p0,
 | 
			
		||||
                          nextMove: (value) {
 | 
			
		||||
                            Navigator.pop(context);
 | 
			
		||||
                            int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
 | 
			
		||||
                            showModalBottomSheet(
 | 
			
		||||
                              context: context,
 | 
			
		||||
                              isScrollControlled: true,
 | 
			
		||||
                              builder: (context) =>
 | 
			
		||||
                                TotalPaymentView(
 | 
			
		||||
                                  listProduct: [
 | 
			
		||||
                                    provider.getSelectedProduct
 | 
			
		||||
                                  ],
 | 
			
		||||
                                  totalInvest: formatIntParse,
 | 
			
		||||
                                )
 | 
			
		||||
                            );
 | 
			
		||||
                          },
 | 
			
		||||
                        );
 | 
			
		||||
                      },
 | 
			
		||||
                    );
 | 
			
		||||
                  },
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class Product {
 | 
			
		||||
  String? name, type;
 | 
			
		||||
  double? yield;
 | 
			
		||||
  double? priceUnit, funds, totalPercent;
 | 
			
		||||
 | 
			
		||||
  Product({this.name, this.type, this.yield, this.priceUnit, this.funds, this.totalPercent = 1});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ProductViewModel extends ChangeNotifier {
 | 
			
		||||
  static Product selectedProduct = Product();
 | 
			
		||||
  Product get getSelectedProduct => selectedProduct;
 | 
			
		||||
 | 
			
		||||
  double totalInvestment = 0;
 | 
			
		||||
 | 
			
		||||
  void setSelectedProduct(Product product) {
 | 
			
		||||
    selectedProduct = product;
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void setTotalInvestment(double value) {
 | 
			
		||||
    totalInvestment = value;
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -39,6 +39,10 @@ class MyApp extends StatelessWidget {
 | 
			
		||||
          secondary: const Color(0xFFFECDA6),
 | 
			
		||||
          onBackground: const Color(0xFFA9A9A9),
 | 
			
		||||
        ),
 | 
			
		||||
        bottomSheetTheme: BottomSheetThemeData(
 | 
			
		||||
          backgroundColor: Colors.white,
 | 
			
		||||
          surfaceTintColor: Colors.white
 | 
			
		||||
        )
 | 
			
		||||
        // useMaterial3: true,
 | 
			
		||||
      ),
 | 
			
		||||
      initialRoute: initialRoute,
 | 
			
		||||
 
 | 
			
		||||