fix: validation input investment

This commit is contained in:
Prajna Prayoga 2024-02-23 14:56:06 +07:00
parent 38837bd4f8
commit d79959c47f
4 changed files with 161 additions and 176 deletions

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:cims_apps/application/component/button/button_view.dart'; import 'package:cims_apps/application/component/button/button_view.dart';
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/application/theme/color_palette.dart';
@ -6,9 +8,13 @@ import 'package:cims_apps/core/utils/size_config.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class InputInvestmentView extends StatefulWidget { class InputInvestmentView extends StatefulWidget {
final String selectedPlan; final String? currentPlan;
final void Function()? changePlan;
final int? currentPrice;
final int? minimumPrice;
final int? maximumPrice;
final void Function(String value) nextMove; final void Function(String value) nextMove;
const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove}); const InputInvestmentView({super.key, required this.nextMove, this.currentPlan, this.minimumPrice, this.maximumPrice, this.currentPrice, this.changePlan});
@override @override
State<InputInvestmentView> createState() => _InputInvestmentViewState(); State<InputInvestmentView> createState() => _InputInvestmentViewState();
@ -17,10 +23,35 @@ class InputInvestmentView extends StatefulWidget {
class _InputInvestmentViewState extends State<InputInvestmentView> { class _InputInvestmentViewState extends State<InputInvestmentView> {
TextEditingController inputController = TextEditingController(); TextEditingController inputController = TextEditingController();
void validationInputValue(String currentValue) {
currentValue = currentValue.replaceAll('Rp ', '').replaceAll('.', '');
if(currentValue.isEmpty){
currentValue = '0';
}
double parseValue = double.parse(currentValue);
if(widget.minimumPrice != null){
if(parseValue <= widget.minimumPrice!){
parseValue = widget.minimumPrice!.toDouble();
}
}
if(widget.maximumPrice != null){
if(parseValue >= widget.maximumPrice!){
parseValue = widget.maximumPrice!.toDouble();
}
}
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
}
@override @override
void initState() { void initState() {
// TODO: implement initState // TODO: implement initState
inputController.text = 'Rp 0'; if(widget.currentPrice != null){
inputController.text = NumberFormatter.numberCurrency(widget.currentPrice, 'Rp ', 'id_ID', decimalDigits: 0);
}else{
inputController.text = 'Rp 0';
}
super.initState(); super.initState();
} }
@ -41,55 +72,53 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox(height: 16),
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( if(widget.currentPlan != null)
mainAxisAlignment: MainAxisAlignment.spaceBetween, Row(
children: [ mainAxisAlignment: MainAxisAlignment.spaceBetween,
Text(widget.selectedPlan, children: [
style: TextStyle( Text(widget.currentPlan ?? '',
fontSize: 20, style: const TextStyle(
fontWeight: FontWeight.w700, fontSize: 20,
fontWeight: FontWeight.w700,
),
), ),
), InkWell(
Row( borderRadius: BorderRadius.circular(16),
children: [ onTap: widget.changePlan,
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20), child: const Row(
SizedBox(width: 4), children: [
Text('Change', Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
style: TextStyle( SizedBox(width: 4),
fontSize: 16, Text('Change',
fontWeight: FontWeight.w600, style: TextStyle(
color: ColorPalette.primary fontSize: 16,
), fontWeight: FontWeight.w600,
) color: ColorPalette.primary
], ),
) )
], ],
), ),
)
],
),
TextField( TextField(
controller: inputController, controller: inputController,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: const TextStyle(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: ColorPalette.slate800 color: ColorPalette.slate800
), ),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
onChanged: (value) { onChanged: (value) {
value = value.replaceAll('Rp ', '').replaceAll('.', ''); validationInputValue(value);
double parseValue = double.parse(value);
if(value.isNotEmpty){
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
}else{
inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
}
}, },
decoration: InputDecoration( decoration: const InputDecoration(
enabledBorder: UnderlineInputBorder( enabledBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: ColorPalette.primary, color: ColorPalette.primary,
@ -98,30 +127,36 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
) )
), ),
), ),
SizedBox(height: 12), const SizedBox(height: 12),
Text('Minimum Budget Rp1,000,000', if(widget.minimumPrice != null)
style: TextStyle( Text('Minimum ${NumberFormatter.numberCurrency(widget.minimumPrice, 'Rp ', 'id_ID')}',
color: ColorPalette.slate400, style: const TextStyle(
fontSize: 16, color: ColorPalette.slate400,
fontWeight: FontWeight.w600 fontSize: 16,
fontWeight: FontWeight.w600
),
), ),
), if(widget.maximumPrice != null)
SizedBox(height: 16), Text('Maximum ${NumberFormatter.numberCurrency(widget.maximumPrice, 'Rp ', 'id_ID')}',
style: const TextStyle(
color: ColorPalette.slate400,
fontSize: 16,
fontWeight: FontWeight.w600
),
),
const SizedBox(height: 16),
NumericPad(onNumberSelected: (p0) { NumericPad(onNumberSelected: (p0) {
String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', ''); String currentValue = inputController.text;
String getNumeric = p0;
if(p0.isNotEmpty){ if(p0.isNotEmpty){
if(checkIsZeroInput != '0'){ if(currentValue != '0'){
getNumeric = checkIsZeroInput + getNumeric; currentValue = currentValue + p0;
} }
}else{ }else{
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1); currentValue = currentValue.substring(0, currentValue.length - 1);
} }
String formatNumeric = NumberFormatter.numberCurrency( validationInputValue(currentValue);
double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
inputController.text = formatNumeric;
}), }),
SizedBox(height: 8), const SizedBox(height: 24),
ButtonView( ButtonView(
name: 'Next', name: 'Next',
onPressed: () { onPressed: () {
@ -129,7 +164,7 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
}, },
width: SizeConfig.width, width: SizeConfig.width,
heightWrapContent: true, heightWrapContent: true,
contentPadding: EdgeInsets.symmetric(vertical: 16), contentPadding: const EdgeInsets.symmetric(vertical: 16),
marginVertical: 0, marginVertical: 0,
) )
], ],
@ -137,6 +172,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
), ),
], ],
), ),
);; );
} }
} }

View File

@ -115,10 +115,13 @@ class _PlanViewState extends State<PlanView> {
), ),
const Divider(color: ColorPalette.slate200, height: 1), const Divider(color: ColorPalette.slate200, height: 1),
InputInvestmentView( InputInvestmentView(
selectedPlan: text, currentPlan: text,
changePlan: () {
Navigator.pop(context);
},
nextMove: (value) { nextMove: (value) {
Navigator.pop(context); Navigator.pop(context);
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse)); showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
}, },
), ),

View File

@ -4,6 +4,7 @@ import 'package:cims_apps/application/assets/path_assets.dart';
import 'package:cims_apps/application/component/button/button_view.dart'; import 'package:cims_apps/application/component/button/button_view.dart';
import 'package:cims_apps/application/component/image/image_view.dart'; import 'package:cims_apps/application/component/image/image_view.dart';
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart'; import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
import 'package:cims_apps/application/component/text_title/text_title.dart'; import 'package:cims_apps/application/component/text_title/text_title.dart';
import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/application/theme/color_palette.dart';
import 'package:cims_apps/core/utils/number_formatter.dart'; import 'package:cims_apps/core/utils/number_formatter.dart';
@ -82,98 +83,33 @@ class _ChangeAmountState extends State<ChangeAmount> {
), ),
), ),
const Divider(height: 1, color: ColorPalette.slate200,), const Divider(height: 1, color: ColorPalette.slate200,),
Padding( Column(
padding: EdgeInsets.all(24), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, Padding(
children: [ padding: EdgeInsets.all(24),
cardProduct(), child: cardProduct()
SizedBox(height: 24), ),
TextField( InputInvestmentView(
controller: amountController, minimumPrice: (provider.getCurrentProduct.priceUnit! * 1).toInt(),
textAlign: TextAlign.center, maximumPrice: (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(),
style: const TextStyle( currentPrice: provider.getAmount!.toInt(),
fontSize: 28, nextMove: (value) {
fontWeight: FontWeight.w600, String formatValueInput = value.replaceAll('Rp ', '').replaceAll('.', '');
color: ColorPalette.slate800 provider.setAmount(double.parse(formatValueInput));
), Navigator.pop(context);
keyboardType: TextInputType.number, showModalBottomSheet(
onChanged: (value) { context: context,
value = value.replaceAll('Rp ', '').replaceAll('.', ''); isScrollControlled: true,
double parseValue = double.parse(value); builder: (context) {
if(value.isNotEmpty){ return const RedeemProduct();
amountController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0); },
}else{ );
amountController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0); },
} )
}, ],
decoration: const InputDecoration( ),
enabledBorder: UnderlineInputBorder( SizedBox(height: 16,)
borderSide: BorderSide(
color: ColorPalette.primary,
width: 2
),
)
),
),
SizedBox(height: 12),
Text(
'Min Redeem: ${(NumberFormatter.numberCurrency(10000, 'Rp ', 'id_ID', decimalDigits: 0))}',
style: TextStyle(
color: ColorPalette.slate400,
fontWeight: FontWeight.w600,
),
),
Text(
'Max Redeem: ${(NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0))}',
style: TextStyle(
color: ColorPalette.slate400,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 24),
NumericPad(onNumberSelected: (p0) {
String checkIsZeroInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', '');
String getNumeric = p0;
if(p0.isNotEmpty){
if(checkIsZeroInput != '0'){
getNumeric = checkIsZeroInput + getNumeric;
}
}else{
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
}
if(getNumeric.isEmpty){
getNumeric = '0';
}
if(double.parse(getNumeric) >= provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!){
getNumeric = (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toString();
}
String formatNumeric = NumberFormatter.numberCurrency(
double.parse(getNumeric).toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
amountController.text = formatNumeric;
}),
const SizedBox(height: 24),
ButtonView(
name: 'Confirm',
textSize: 20,
marginVertical: 0,
onPressed: () {
String formatValueInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', '');
provider.setAmount(double.parse(formatValueInput));
Navigator.pop(context);
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return const RedeemProduct();
},
);
},
)
],
),
)
], ],
); );
} }

View File

@ -55,32 +55,43 @@ class SelectGoalInvesting extends StatelessWidget {
create: (context) => ProductViewModel(), create: (context) => ProductViewModel(),
child: Consumer<ProductViewModel>( child: Consumer<ProductViewModel>(
builder: (context, provider, child) { builder: (context, provider, child) {
return InputInvestmentView( return Padding(
selectedPlan: p0, padding: EdgeInsets.symmetric(vertical: 16),
nextMove: (value) { child: InputInvestmentView(
Navigator.pop(context); currentPlan: p0,
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', '')); changePlan: () {
showModalBottomSheet( Navigator.pop(context);
context: context, showModalBottomSheet(
isScrollControlled: true, context: context,
builder: (context) => isScrollControlled: true,
ChangeNotifierProvider( builder: (context) => SelectGoalInvesting(),
create: (context) => ProductViewModel(), );
child: Consumer<ProductViewModel>( },
builder: (context, provider, child) { nextMove: (value) {
return TotalPaymentView( Navigator.pop(context);
listProduct: [ int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
provider.getSelectedProduct showModalBottomSheet(
], context: context,
totalInvest: formatIntParse, isScrollControlled: true,
isAgree: provider.isAgree, builder: (context) =>
onTapAgree: provider.setAgree, ChangeNotifierProvider(
); create: (context) => ProductViewModel(),
} child: Consumer<ProductViewModel>(
), builder: (context, provider, child) {
) return TotalPaymentView(
); listProduct: [
}, provider.getSelectedProduct
],
totalInvest: formatIntParse,
isAgree: provider.isAgree,
onTapAgree: provider.setAgree,
);
}
),
)
);
},
),
); );
} }
), ),