feat: flow subscribe product
This commit is contained in:
@@ -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,221 +0,0 @@
|
||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/result_options_product.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ResultTotalProduct extends StatelessWidget {
|
||||
final int totalInvest;
|
||||
final List<Product> listProduct;
|
||||
const ResultTotalProduct({super.key, required this.listProduct, required this.totalInvest});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16)
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Your Investment Today',
|
||||
style: TextStyle(
|
||||
color: ColorPalette.slate800,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.pop(context),
|
||||
child: Icon(Icons.close_rounded)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
...listProduct.asMap().entries.map((e) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 16, right: 24, bottom: 16, top: 16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: ColorPalette.investTypeColor[e.value.type]!,
|
||||
width: 8,
|
||||
)
|
||||
)
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Text(e.value.name,
|
||||
style: 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
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const 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,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
color: ColorPalette.slate800
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
buttonAgreement(),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Total Payment',
|
||||
style: TextStyle(
|
||||
color: ColorPalette.slate400,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16
|
||||
),
|
||||
),
|
||||
Text(NumberFormatter.numberCurrency(totalInvest, 'Rp ', 'id_ID'),
|
||||
textAlign: TextAlign.end,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
color: ColorPalette.slate800
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
ButtonView(
|
||||
disabled: true,
|
||||
name: 'Subscribe Now',
|
||||
onPressed: () {
|
||||
|
||||
},
|
||||
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
||||
textColor: ColorPalette.slate400,
|
||||
textWeight: FontWeight.w700,
|
||||
textSize: 20,
|
||||
backgroundColor: ColorPalette.primary,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buttonAgreement() {
|
||||
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,
|
||||
),
|
||||
),
|
||||
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.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorPalette.slate400
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
child: Text('Read More',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.underline,
|
||||
color: ColorPalette.primary
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user