yoga #16
BIN
assets/icons/icon-navigation-home.png
Normal file
BIN
assets/icons/icon-navigation-home.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/icons/icon-navigation-plan.png
Normal file
BIN
assets/icons/icon-navigation-plan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/icons/icon-navigation-portfolio.png
Normal file
BIN
assets/icons/icon-navigation-portfolio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/icons/icon-navigation-profile.png
Normal file
BIN
assets/icons/icon-navigation-profile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/icons/icon-navigation-transaction.png
Normal file
BIN
assets/icons/icon-navigation-transaction.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 899 B |
BIN
assets/icons/icon-remove.png
Normal file
BIN
assets/icons/icon-remove.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -49,6 +49,12 @@ class PathAssets {
|
||||||
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
||||||
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
||||||
static const String iconCar = 'assets/icons/icon-car.png';
|
static const String iconCar = 'assets/icons/icon-car.png';
|
||||||
|
static const String iconNavigationHome = 'assets/icons/icon-navigation-home.png';
|
||||||
|
static const String iconNavigationPlan = 'assets/icons/icon-navigation-plan.png';
|
||||||
|
static const String iconNavigationTransaction = 'assets/icons/icon-navigation-transaction.png';
|
||||||
|
static const String iconNavigationPortfolio = 'assets/icons/icon-navigation-portfolio.png';
|
||||||
|
static const String iconNavigationProfile = 'assets/icons/icon-navigation-profile.png';
|
||||||
|
static const String iconRemove = 'assets/icons/icon-remove.png';
|
||||||
|
|
||||||
/// IMAGE
|
/// IMAGE
|
||||||
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
||||||
|
@ -86,4 +92,20 @@ class PathAssets {
|
||||||
static const String imgPaymentSuccess = 'assets/images/img-payment-success.png';
|
static const String imgPaymentSuccess = 'assets/images/img-payment-success.png';
|
||||||
static const String frameSignature = 'assets/images/frame-signature.png';
|
static const String frameSignature = 'assets/images/frame-signature.png';
|
||||||
static const String imgFinish = 'assets/images/img-finish.png';
|
static const String imgFinish = 'assets/images/img-finish.png';
|
||||||
|
|
||||||
|
static const Map<String, String> goalInvestIcon = {
|
||||||
|
'Education': iconToga,
|
||||||
|
'Marriage': iconCake,
|
||||||
|
'Old age days': iconHouse,
|
||||||
|
'Home': iconHouse,
|
||||||
|
'Other Plan': iconCreatePlan,
|
||||||
|
'Create Plan': iconCreatePlan,
|
||||||
|
'Entertainment': iconTicket,
|
||||||
|
'Gadget': iconGadget,
|
||||||
|
'Business': iconMarket,
|
||||||
|
'Fashion': iconBag,
|
||||||
|
'Shop': iconBag,
|
||||||
|
'Vehicle': iconCar,
|
||||||
|
'Holiday': iconPlane,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
const CustomAppBar({
|
const CustomAppBar({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.height,
|
required this.height,
|
||||||
this.leading,
|
|
||||||
required this.title,
|
required this.title,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
|
this.leading,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -101,8 +103,9 @@ class NumericPad extends StatelessWidget {
|
||||||
number,
|
number,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: FontWeight.bold
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -117,8 +120,9 @@ class NumericPad extends StatelessWidget {
|
||||||
onNumberSelected('');
|
onNumberSelected('');
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.highlight_remove,
|
Icons.backspace_outlined,
|
||||||
size: 28,
|
size: 28,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
73
lib/application/component/radio_agreement.dart
Normal file
73
lib/application/component/radio_agreement.dart
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class RadioAgreement extends StatelessWidget {
|
||||||
|
final void Function() onTap;
|
||||||
|
final bool isAgree;
|
||||||
|
final String desc;
|
||||||
|
const RadioAgreement({super.key, required this.isAgree, required this.desc, required this.onTap,});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: AnimatedContainer(
|
||||||
|
margin: const EdgeInsets.only(top: 4),
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: isAgree
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate200)),
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
isAgree ? ColorPalette.primary : ColorPalette.white,
|
||||||
|
shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
desc,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: const Text(
|
||||||
|
'Read More',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
color: ColorPalette.primary),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,8 +36,8 @@ class GoalInvestingView extends StatelessWidget {
|
||||||
routePush(
|
routePush(
|
||||||
context,
|
context,
|
||||||
page: OtherPlanView(
|
page: OtherPlanView(
|
||||||
selectedPlan: (value) {
|
selectedPlan: (val) {
|
||||||
onListSelected(e.value.title);
|
onListSelected(val);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,7 +54,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
|
@ -72,6 +74,8 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
||||||
disabled: !(selectedPlan.img != ''),
|
disabled: !(selectedPlan.img != ''),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
print('haloo');
|
||||||
|
print(selectedPlan.name);
|
||||||
widget.selectedPlan(selectedPlan.name);
|
widget.selectedPlan(selectedPlan.name);
|
||||||
},
|
},
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
|
@ -91,6 +95,7 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
||||||
if(plan.name == 'Create Plan'){
|
if(plan.name == 'Create Plan'){
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
builder: (context) => modalCreatePlan(),
|
builder: (context) => modalCreatePlan(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -150,6 +155,9 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
setState(() {
|
||||||
|
selectedPlan = Plan('', '');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: Icon(Icons.close_rounded),
|
child: Icon(Icons.close_rounded),
|
||||||
)
|
)
|
||||||
|
@ -161,12 +169,12 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
||||||
),
|
),
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Select',
|
name: 'Next',
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
disabled: !(createController.text != ''),
|
disabled: !(createController.text != ''),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context)..pop()..pop();
|
Navigator.of(context)..pop()..pop();
|
||||||
widget.selectedPlan(selectedPlan.name);
|
widget.selectedPlan(createController.text);
|
||||||
},
|
},
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/radio_agreement.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
@ -6,22 +7,19 @@ import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TotalPaymentView extends StatefulWidget {
|
class TotalPaymentView extends StatelessWidget {
|
||||||
final int totalInvest;
|
final int totalInvest;
|
||||||
final List<Product> listProduct;
|
final List<Product> listProduct;
|
||||||
|
final bool isAgree;
|
||||||
|
final void Function() onTapAgree;
|
||||||
const TotalPaymentView({
|
const TotalPaymentView({
|
||||||
super.key,
|
super.key,
|
||||||
required this.listProduct,
|
required this.listProduct,
|
||||||
required this.totalInvest,
|
required this.totalInvest,
|
||||||
|
required this.isAgree,
|
||||||
|
required this.onTapAgree,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
State<TotalPaymentView> createState() => _TotalPaymentViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TotalPaymentViewState extends State<TotalPaymentView> {
|
|
||||||
bool isAgreement = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
@ -49,7 +47,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...widget.listProduct.asMap().entries.map((e) {
|
...listProduct.asMap().entries.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 16, right: 24, bottom: 16, top: 16),
|
left: 16, right: 24, bottom: 16, top: 16),
|
||||||
|
@ -75,7 +73,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
flex: 7,
|
flex: 7,
|
||||||
child: Text(
|
child: Text(
|
||||||
NumberFormatter.numberCurrency(
|
NumberFormatter.numberCurrency(
|
||||||
widget.totalInvest * e.value.totalPercent!,
|
totalInvest * e.value.totalPercent!,
|
||||||
'Rp ',
|
'Rp ',
|
||||||
'id_ID'),
|
'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
|
@ -129,7 +127,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
NumberFormatter.numberCurrency(
|
NumberFormatter.numberCurrency(
|
||||||
widget.totalInvest, 'Rp ', 'id_ID'),
|
totalInvest, 'Rp ', 'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
@ -139,7 +137,14 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
buttonAgreement(),
|
RadioAgreement(
|
||||||
|
isAgree: isAgree,
|
||||||
|
desc: 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision. Read More',
|
||||||
|
onTap: () {
|
||||||
|
print('gagaga');
|
||||||
|
onTapAgree();
|
||||||
|
},
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -154,7 +159,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
NumberFormatter.numberCurrency(
|
NumberFormatter.numberCurrency(
|
||||||
widget.totalInvest, 'Rp ', 'id_ID'),
|
totalInvest, 'Rp ', 'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
@ -165,16 +170,16 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
disabled: !isAgreement,
|
disabled: !isAgree,
|
||||||
name: 'Subscribe Now',
|
name: 'Subscribe Now',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: PaymentMethodView(
|
page: PaymentMethodView(
|
||||||
totalInvest: widget.totalInvest,
|
totalInvest: totalInvest,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
||||||
textColor: isAgreement ? Colors.white : ColorPalette.slate400,
|
textColor: isAgree ? Colors.white : ColorPalette.slate400,
|
||||||
textWeight: FontWeight.w700,
|
textWeight: FontWeight.w700,
|
||||||
textSize: 20,
|
textSize: 20,
|
||||||
backgroundColor: ColorPalette.primary,
|
backgroundColor: ColorPalette.primary,
|
||||||
|
@ -185,71 +190,67 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buttonAgreement() {
|
// Widget buttonAgreement() {
|
||||||
bool isAgree = isAgreement;
|
// return Padding(
|
||||||
return Padding(
|
// padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
// child: Row(
|
||||||
child: Row(
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// children: [
|
||||||
children: [
|
// GestureDetector(
|
||||||
GestureDetector(
|
// onTap: () {
|
||||||
onTap: () {
|
// },
|
||||||
setState(() {
|
// child: AnimatedContainer(
|
||||||
isAgreement = !isAgreement;
|
// margin: const EdgeInsets.only(top: 4),
|
||||||
});
|
// duration: const Duration(milliseconds: 200),
|
||||||
},
|
// height: 16,
|
||||||
child: AnimatedContainer(
|
// width: 16,
|
||||||
margin: const EdgeInsets.only(top: 4),
|
// padding: const EdgeInsets.all(1),
|
||||||
duration: const Duration(milliseconds: 200),
|
// alignment: Alignment.center,
|
||||||
height: 16,
|
// decoration: BoxDecoration(
|
||||||
width: 16,
|
// shape: BoxShape.circle,
|
||||||
padding: const EdgeInsets.all(1),
|
// border: Border.all(
|
||||||
alignment: Alignment.center,
|
// color: isAgree
|
||||||
decoration: BoxDecoration(
|
// ? ColorPalette.primary
|
||||||
shape: BoxShape.circle,
|
// : ColorPalette.slate200)),
|
||||||
border: Border.all(
|
// child: AnimatedContainer(
|
||||||
color: isAgree
|
// duration: const Duration(milliseconds: 200),
|
||||||
? ColorPalette.primary
|
// child: Container(
|
||||||
: ColorPalette.slate200)),
|
// decoration: BoxDecoration(
|
||||||
child: AnimatedContainer(
|
// color:
|
||||||
duration: const Duration(milliseconds: 200),
|
// isAgree ? ColorPalette.primary : ColorPalette.white,
|
||||||
child: Container(
|
// shape: BoxShape.circle),
|
||||||
decoration: BoxDecoration(
|
// ),
|
||||||
color:
|
// ),
|
||||||
isAgree ? ColorPalette.primary : ColorPalette.white,
|
// ),
|
||||||
shape: BoxShape.circle),
|
// ),
|
||||||
),
|
// const SizedBox(
|
||||||
),
|
// width: 12,
|
||||||
),
|
// ),
|
||||||
),
|
// Expanded(
|
||||||
const SizedBox(
|
// child: Column(
|
||||||
width: 12,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
),
|
// children: [
|
||||||
Expanded(
|
// const Text(
|
||||||
child: Column(
|
// 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// style: TextStyle(
|
||||||
children: [
|
// fontSize: 16,
|
||||||
const Text(
|
// fontWeight: FontWeight.w600,
|
||||||
'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
|
// color: ColorPalette.slate400),
|
||||||
style: TextStyle(
|
// ),
|
||||||
fontSize: 16,
|
// GestureDetector(
|
||||||
fontWeight: FontWeight.w600,
|
// onTap: () {},
|
||||||
color: ColorPalette.slate400),
|
// child: const Text(
|
||||||
),
|
// 'Read More',
|
||||||
GestureDetector(
|
// style: TextStyle(
|
||||||
onTap: () {},
|
// fontSize: 16,
|
||||||
child: const Text(
|
// fontWeight: FontWeight.w600,
|
||||||
'Read More',
|
// decoration: TextDecoration.underline,
|
||||||
style: TextStyle(
|
// color: ColorPalette.primary),
|
||||||
fontSize: 16,
|
// ))
|
||||||
fontWeight: FontWeight.w600,
|
// ],
|
||||||
decoration: TextDecoration.underline,
|
// ))
|
||||||
color: ColorPalette.primary),
|
// ],
|
||||||
))
|
// ),
|
||||||
],
|
// );
|
||||||
))
|
// }
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ class ColorPalette {
|
||||||
static const Color green100 = Color(0xFFDCFCE7);
|
static const Color green100 = Color(0xFFDCFCE7);
|
||||||
static const Color green400 = Color(0xFF4ADE80);
|
static const Color green400 = Color(0xFF4ADE80);
|
||||||
static const Color green500 = Color(0xFF16A34A);
|
static const Color green500 = Color(0xFF16A34A);
|
||||||
|
static const Color red600 = Color(0xffDC2626);
|
||||||
|
|
||||||
static const Map<String, Color> investTypeColor = {
|
static const Map<String, Color> investTypeColor = {
|
||||||
'Money Market': purple500,
|
'Money Market': purple500,
|
||||||
|
|
|
@ -56,17 +56,24 @@ class _QuestionViewState extends State<QuestionView> {
|
||||||
bottomNavigationBar: SizedBox(
|
bottomNavigationBar: SizedBox(
|
||||||
height: 84,
|
height: 84,
|
||||||
child: ButtonView(
|
child: ButtonView(
|
||||||
|
disabled: provider.listScore[currentPage] == 0,
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
marginVertical: 16,
|
marginVertical: 16,
|
||||||
|
disabledBgColor: ColorPalette.slate200,
|
||||||
|
textColor: provider.listScore[currentPage] == 0 ? ColorPalette.slate500 : Colors.white,
|
||||||
|
backgroundColor: ColorPalette.primary,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (currentPage > 3) {
|
if (currentPage > 3) {
|
||||||
int totalScore = provider.listScore
|
int totalScore = provider.listScore
|
||||||
.reduce((value, element) => value + element);
|
.reduce((value, element) => value + element);
|
||||||
provider.setTypeResult(totalScore);
|
provider.setTypeResult(totalScore);
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: ResultsView(
|
page: ResultsView(
|
||||||
totalScore: totalScore.toString(),
|
totalScore: totalScore,
|
||||||
typeResult: provider.typeResult));
|
typeResult: provider.typeResult
|
||||||
|
),
|
||||||
|
routeType: RouteType.pushReplace
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
currentPage += 1;
|
currentPage += 1;
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/risk_profile.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/question_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/terms_and_condition/terms_and_condition_view.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/terms_and_condition/terms_and_condition_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ResultsView extends StatelessWidget {
|
class ResultsView extends StatelessWidget {
|
||||||
final String totalScore;
|
final int totalScore;
|
||||||
final RiskProfileResult typeResult;
|
final RiskProfileResult typeResult;
|
||||||
const ResultsView(
|
const ResultsView(
|
||||||
{super.key, required this.typeResult, required this.totalScore});
|
{super.key, required this.typeResult, required this.totalScore});
|
||||||
|
@ -37,115 +40,15 @@ class ResultsView extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
RiskProfile(totalScore: totalScore, rowSuitableProduct: false),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: typeResult.color,
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage(typeResult.img),
|
|
||||||
alignment: Alignment.centerRight)),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(24),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
typeResult.type,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 24,
|
|
||||||
color: ColorPalette.white),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
'Total Score :',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 16,
|
|
||||||
color: ColorPalette.white),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
totalScore,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 28,
|
|
||||||
color: ColorPalette.white),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 24,
|
|
||||||
),
|
|
||||||
Text(typeResult.desc,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: ColorPalette.slate500, fontSize: 16)),
|
|
||||||
const SizedBox(
|
|
||||||
height: 24,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
'Suitable Product',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate800,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 16),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
Wrap(
|
|
||||||
runSpacing: 16,
|
|
||||||
children: typeResult.suitableProduct.map((e) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
color: typeResult.color.withOpacity(0.1)),
|
|
||||||
child: Image.asset(e['icon'],
|
|
||||||
width: SizeConfig.width * 0.07,
|
|
||||||
color: typeResult.color)),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
e['desc'],
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: ColorPalette.slate800),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 32,
|
height: 32,
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Re-test',
|
name: 'Re-test',
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
routePush(context, page: QuestionView(), routeType: RouteType.pushReplace);
|
||||||
|
},
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
backgroundColor: ColorPalette.white,
|
backgroundColor: ColorPalette.white,
|
||||||
textColor: ColorPalette.primary,
|
textColor: ColorPalette.primary,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/plan_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/plan_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart';
|
||||||
|
@ -6,6 +8,12 @@ import 'package:cims_apps/features/profile/view/profile_view.dart';
|
||||||
import 'package:cims_apps/features/transaction/view/transaction_view.dart';
|
import 'package:cims_apps/features/transaction/view/transaction_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BottomNavigationItem {
|
||||||
|
String icon, label;
|
||||||
|
|
||||||
|
BottomNavigationItem(this.icon, this.label);
|
||||||
|
}
|
||||||
|
|
||||||
class BottomNavigationView extends StatefulWidget {
|
class BottomNavigationView extends StatefulWidget {
|
||||||
const BottomNavigationView({Key? key}) : super(key: key);
|
const BottomNavigationView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -26,32 +34,20 @@ class _BottomNavigationViewState extends State<BottomNavigationView> {
|
||||||
ProfileView(),
|
ProfileView(),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<BottomNavigationBarItem> listNavigation = const [
|
List<BottomNavigationItem> listNavigation = [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationItem(PathAssets.iconNavigationHome, 'Home'),
|
||||||
icon: Icon(Icons.home_outlined),
|
BottomNavigationItem(PathAssets.iconNavigationPlan, 'Plan'),
|
||||||
label: 'Home',
|
BottomNavigationItem(PathAssets.iconNavigationTransaction, 'Transaction'),
|
||||||
),
|
BottomNavigationItem(PathAssets.iconNavigationPortfolio, 'Portfolio'),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationItem(PathAssets.iconNavigationProfile, 'Profile')
|
||||||
icon: Icon(Icons.file_open),
|
|
||||||
label: 'Plan',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.compare_arrows),
|
|
||||||
label: 'Transaction',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.pie_chart_rounded),
|
|
||||||
label: 'Portfolio',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.person),
|
|
||||||
label: 'Profile',
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: listWidget[_selectedIndex],
|
body: listWidget[_selectedIndex],
|
||||||
bottomNavigationBar: Padding(
|
bottomNavigationBar: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(top: BorderSide(color: ColorPalette.slate200))
|
||||||
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
child: BottomNavigationBar(
|
child: BottomNavigationBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
@ -61,13 +57,25 @@ class _BottomNavigationViewState extends State<BottomNavigationView> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
currentIndex: _selectedIndex,
|
currentIndex: _selectedIndex,
|
||||||
items: listNavigation,
|
items: listNavigation.asMap().entries.map((e) {
|
||||||
|
return BottomNavigationBarItem(
|
||||||
|
icon: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
|
child: Image.asset(
|
||||||
|
e.value.icon,
|
||||||
|
width: SizeConfig.width * 0.06,
|
||||||
|
color: e.key == _selectedIndex ? ColorPalette.primary : ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
label: e.value.label
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
showUnselectedLabels: true,
|
showUnselectedLabels: true,
|
||||||
selectedItemColor: ColorPalette.primary,
|
selectedItemColor: ColorPalette.primary,
|
||||||
unselectedItemColor: Colors.black,
|
unselectedItemColor: Colors.black,
|
||||||
selectedLabelStyle: const TextStyle(color: ColorPalette.primary),
|
selectedLabelStyle: const TextStyle(color: ColorPalette.primary, fontSize: 12),
|
||||||
unselectedLabelStyle: const TextStyle(color: Colors.black),
|
unselectedLabelStyle: const TextStyle(color: Colors.black, fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -102,7 +102,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
provider.setSelectedProduct(e.value);
|
provider.setSelectedProduct(e.value);
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: ProductView(widget.title));
|
page: ProductView(selectedProduct: e.value));
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
|
|
|
@ -40,42 +40,50 @@ class _PlanViewState extends State<PlanView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Scaffold(
|
return ChangeNotifierProvider(
|
||||||
appBar: CustomAppBar(height: 70, title: 'Investment Plan'),
|
create: (context) => PlanViewModel(),
|
||||||
body: SingleChildScrollView(
|
child: Scaffold(
|
||||||
padding: EdgeInsets.all(24),
|
appBar: CustomAppBar(
|
||||||
child: Column(
|
height: SizeConfig.height * 0.08,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
title: 'Investment Plan',
|
||||||
children: [
|
leading: SizedBox(),
|
||||||
RiskProfile(
|
),
|
||||||
totalScore: 26,
|
body: SingleChildScrollView(
|
||||||
rowSuitableProduct: true
|
padding: EdgeInsets.all(24),
|
||||||
),
|
child: Column(
|
||||||
SizedBox(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
height: 32,
|
children: [
|
||||||
),
|
RiskProfile(
|
||||||
Text('Your Goal in Investing',
|
totalScore: 26,
|
||||||
style: TextStyle(
|
rowSuitableProduct: true
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: ColorPalette.slate800,
|
|
||||||
fontSize: 18
|
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: 32,
|
||||||
height: 24,
|
),
|
||||||
),
|
Text('Your Goal in Investing',
|
||||||
GoalInvestingView(
|
style: TextStyle(
|
||||||
onListSelected: (p0) {
|
fontWeight: FontWeight.w700,
|
||||||
showModalBottomSheet(
|
color: ColorPalette.slate800,
|
||||||
context: context,
|
fontSize: 18
|
||||||
isScrollControlled: true,
|
),
|
||||||
builder: (context) {
|
),
|
||||||
return modalInvest(context, p0);
|
SizedBox(
|
||||||
},
|
height: 24,
|
||||||
);
|
),
|
||||||
},
|
GoalInvestingView(
|
||||||
)
|
onListSelected: (p0) {
|
||||||
],
|
print(p0);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return modalInvest(context, p0);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,9 +3,14 @@ import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/options_starting_invest.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class ResultOptionsProduct extends StatelessWidget {
|
class ResultOptionsProduct extends StatelessWidget {
|
||||||
final int totalInvest;
|
final int totalInvest;
|
||||||
|
@ -19,134 +24,169 @@ class ResultOptionsProduct extends StatelessWidget {
|
||||||
Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1)
|
Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1)
|
||||||
];
|
];
|
||||||
|
|
||||||
return Container(
|
return ChangeNotifierProvider(
|
||||||
decoration: BoxDecoration(
|
create: (context) => PlanViewModel(),
|
||||||
color: Colors.white,
|
child: Consumer<PlanViewModel>(
|
||||||
borderRadius: BorderRadius.circular(16)
|
builder: (context, provider, child) {
|
||||||
),
|
return Container(
|
||||||
padding: const EdgeInsets.all(24),
|
decoration: BoxDecoration(
|
||||||
child: Column(
|
color: Colors.white,
|
||||||
mainAxisSize: MainAxisSize.min,
|
borderRadius: BorderRadius.circular(16)
|
||||||
children: [
|
),
|
||||||
const Row(
|
padding: const EdgeInsets.all(24),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Icon(Icons.arrow_back, color: ColorPalette.slate500),
|
|
||||||
Text('Results from your risk profile',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 18,
|
|
||||||
color: ColorPalette.slate800
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Icon(Icons.close_rounded, color: ColorPalette.slate400)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 32),
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: listProduct.asMap().entries.map((e) {
|
mainAxisSize: MainAxisSize.min,
|
||||||
return Container(
|
children: [
|
||||||
margin: const EdgeInsets.only(bottom: 16),
|
Row(
|
||||||
padding: const EdgeInsets.all(16),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
decoration: BoxDecoration(
|
children: [
|
||||||
color: Colors.white,
|
GestureDetector(
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
onTap: () {
|
||||||
borderRadius: BorderRadius.circular(12),
|
Navigator.pop(context);
|
||||||
boxShadow: const [
|
showModalBottomSheet(
|
||||||
BoxShadow(
|
context: context,
|
||||||
color: Color(0XFF1E293B0A)
|
builder: (context) {
|
||||||
)
|
return OptionsStartingInvest(totalInvest: totalInvest);
|
||||||
]
|
},
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
child: Icon(Icons.arrow_back, color: ColorPalette.slate500)
|
||||||
|
),
|
||||||
|
Text('Results from your risk profile',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 18,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Icon(Icons.close_rounded, color: ColorPalette.slate400)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: listProduct.asMap().entries.map((e) {
|
||||||
Row(
|
return Container(
|
||||||
children: [
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
const ImageView(image: PathAssets.iconGoogle, width: 30,),
|
padding: const EdgeInsets.all(16),
|
||||||
const SizedBox(
|
decoration: BoxDecoration(
|
||||||
width: 12,
|
color: Colors.white,
|
||||||
),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
Expanded(
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: Column(
|
boxShadow: const [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
BoxShadow(
|
||||||
|
color: Color(0XFF1E293B0A)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(e.value.name ?? '',
|
const ImageView(image: PathAssets.iconGoogle, width: 30,),
|
||||||
style: const TextStyle(
|
const SizedBox(
|
||||||
fontWeight: FontWeight.w700,
|
width: 12,
|
||||||
color: ColorPalette.slate800,
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(e.value.name ?? '',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4,),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: ColorPalette.investTypeColor[e.value.type]!),
|
||||||
|
color: ColorPalette.investTypeBgColor[e.value.type],
|
||||||
|
borderRadius: BorderRadius.circular(40)
|
||||||
|
),
|
||||||
|
child: Text(e.value.type ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor[e.value.type],
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 12
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4,),
|
Text('${(e.value.totalPercent! * 100).toInt()} %',
|
||||||
Container(
|
style: const TextStyle(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
fontWeight: FontWeight.w700,
|
||||||
decoration: BoxDecoration(
|
fontSize: 16,
|
||||||
border: Border.all(color: ColorPalette.investTypeColor[e.value.type]!),
|
color: ColorPalette.slate800
|
||||||
color: ColorPalette.investTypeBgColor[e.value.type],
|
|
||||||
borderRadius: BorderRadius.circular(40)
|
|
||||||
),
|
|
||||||
child: Text(e.value.type ?? '',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.investTypeColor[e.value.type],
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 12
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
const Padding(
|
||||||
Text('${(e.value.totalPercent! * 100).toInt()} %',
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
style: const TextStyle(
|
child: Divider(height: 1, color: ColorPalette.slate200),
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
fontSize: 16,
|
|
||||||
color: ColorPalette.slate800
|
|
||||||
),
|
),
|
||||||
)
|
GestureDetector(
|
||||||
],
|
onTap: () {
|
||||||
),
|
routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true));
|
||||||
const Padding(
|
},
|
||||||
padding: EdgeInsets.symmetric(vertical: 16),
|
child: const Text('See More',
|
||||||
child: Divider(height: 1, color: ColorPalette.slate200),
|
style: TextStyle(
|
||||||
),
|
color: ColorPalette.slate500,
|
||||||
GestureDetector(
|
fontWeight: FontWeight.w600,
|
||||||
onTap: () {
|
),
|
||||||
},
|
),
|
||||||
child: const Text('See More',
|
)
|
||||||
style: TextStyle(
|
],
|
||||||
color: ColorPalette.slate500,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
],
|
}).toList(),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}).toList(),
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) =>
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => PlanViewModel(),
|
||||||
|
child: Consumer<PlanViewModel>(
|
||||||
|
builder: (context, planProvider, _) {
|
||||||
|
return TotalPaymentView(
|
||||||
|
listProduct: listProduct,
|
||||||
|
totalInvest: totalInvest,
|
||||||
|
isAgree: planProvider.isAgree,
|
||||||
|
onTapAgree: planProvider.setAgree,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
width: SizeConfig.width,
|
||||||
|
heightWrapContent: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
marginVertical: 0,
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
const SizedBox(
|
}
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
ButtonView(
|
|
||||||
name: 'Next',
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (context) =>
|
|
||||||
TotalPaymentView(
|
|
||||||
listProduct: listProduct,
|
|
||||||
totalInvest: totalInvest,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
width: SizeConfig.width,
|
|
||||||
heightWrapContent: true,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
marginVertical: 0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,10 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class PlanViewModel extends ChangeNotifier {
|
class PlanViewModel extends ChangeNotifier {
|
||||||
List<Product> listProduct = [];
|
List<Product> listProduct = [];
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class PortfolioDetailView extends StatelessWidget {
|
||||||
|
const PortfolioDetailView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<PortfolioProduct> listProduct = [
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000),
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Likuid',
|
||||||
|
type: '',
|
||||||
|
yield: 6.42,
|
||||||
|
priceUnit: 1600.79,
|
||||||
|
funds: 2340000),
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Income Fund',
|
||||||
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000)
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider(create: (context) => RedeemProductViewModel())
|
||||||
|
],
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: SizedBox(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
height: SizeConfig.height,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 50,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BackButtonView(),
|
||||||
|
const TextTitle(title: 'Education', color: Colors.white),
|
||||||
|
SizedBox(width: SizeConfig.width * 0.1,)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24,),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Portfolio Value',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.white,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text('Advantages',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.white,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24,),
|
||||||
|
Expanded(
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(0),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
children: [
|
||||||
|
cardPortfolio(context)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardPortfolio(context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Money Market' ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor['Money Market'],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
),
|
||||||
|
Wrap(
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
rowDescription('Present Value', 'Rp2.660.706', fontWeight: FontWeight.w700),
|
||||||
|
rowDescription('Investment Capital', 'Rp2.660.706'),
|
||||||
|
rowDescription('Advantages', 'Rp2.660.706'),
|
||||||
|
rowDescription('Purchase Price', 'Rp1.500,57'),
|
||||||
|
rowDescription('Number of Units', '14.002'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16,),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ButtonView(
|
||||||
|
name: 'Redeem',
|
||||||
|
marginVertical: 0,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
isOutlined: true,
|
||||||
|
heightWrapContent: true,
|
||||||
|
contentPadding: const EdgeInsets.all(12),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
borderColor: ColorPalette.red600,
|
||||||
|
textColor: ColorPalette.red600,
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: ButtonView(
|
||||||
|
name: 'Buy',
|
||||||
|
marginVertical: 0,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
heightWrapContent: true,
|
||||||
|
contentPadding: const EdgeInsets.all(12),
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget rowDescription(String title, String value, {Color? color, FontWeight? fontWeight}) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(value,
|
||||||
|
style: TextStyle(
|
||||||
|
color: color ?? ColorPalette.slate800,
|
||||||
|
fontWeight: fontWeight ?? FontWeight.w600,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -147,9 +150,31 @@ class _PortofolioViewState extends State<PortofolioView> {
|
||||||
),
|
),
|
||||||
menuPortofolio(),
|
menuPortofolio(),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 12,
|
||||||
),
|
),
|
||||||
...listColumnPortofolio(),
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: 'My Portfolio', fontSize: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.add, size: 18, color: ColorPalette.primary),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
const Text('Create',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// ...listColumnPortofolio(),
|
||||||
|
cardPortfolio()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -183,6 +208,7 @@ class _PortofolioViewState extends State<PortofolioView> {
|
||||||
seePortofolioValue
|
seePortofolioValue
|
||||||
? Icons.visibility_off_outlined
|
? Icons.visibility_off_outlined
|
||||||
: Icons.visibility_outlined,
|
: Icons.visibility_outlined,
|
||||||
|
size: 18,
|
||||||
color: const Color(0xff93C5FD)))
|
color: const Color(0xff93C5FD)))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -358,4 +384,85 @@ class _PortofolioViewState extends State<PortofolioView> {
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget cardPortfolio() {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context, page: const PortfolioDetailView());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorPalette.blue200.withOpacity(0.5),
|
||||||
|
borderRadius: BorderRadius.circular(8)
|
||||||
|
),
|
||||||
|
child: ImageView(
|
||||||
|
image: PathAssets.goalInvestIcon['Education'],
|
||||||
|
width: SizeConfig.width * 0.07
|
||||||
|
)
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: 'Education', fontSize: 16,),
|
||||||
|
Text('2 Subscriptions',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Divider(height: 1, color: ColorPalette.slate200),
|
||||||
|
),
|
||||||
|
const Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Portfolio Value',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14,)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text('Advantages',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ChangeAmount extends StatefulWidget {
|
||||||
|
final int totalAmount;
|
||||||
|
const ChangeAmount({super.key, required this.totalAmount});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChangeAmount> createState() => _ChangeAmountState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChangeAmountState extends State<ChangeAmount> {
|
||||||
|
TextEditingController amountController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// TODO: implement initState
|
||||||
|
super.initState();
|
||||||
|
amountController.text = NumberFormatter.numberCurrency(widget.totalAmount, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
super.dispose();
|
||||||
|
amountController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_back_rounded)
|
||||||
|
),
|
||||||
|
const Text('Type amount',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.close_rounded)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
cardProduct(),
|
||||||
|
SizedBox(height: 24),
|
||||||
|
TextField(
|
||||||
|
controller: amountController,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const 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){
|
||||||
|
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(
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct() {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Money Market' ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor['Money Market'],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ChangeDestinationAccount extends StatelessWidget {
|
||||||
|
const ChangeDestinationAccount({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Account> listAccount = [
|
||||||
|
Account('Muhamad Rosyidin', 'BRI', '902139012324'),
|
||||||
|
Account('Achmad Muhaimin', 'BCA', '21391283928')
|
||||||
|
];
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_back_rounded)
|
||||||
|
),
|
||||||
|
const Text('Change Destination Account',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.close_rounded)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
...listAccount.asMap().entries.map((e) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => provider.setSelectedAcc(e.value),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: e.key != 0 ? 16 : 0),
|
||||||
|
child: cardAccount(e.value, provider.selectedAccount?.number ?? provider.getCurrentAccount.number),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
GestureDetector(
|
||||||
|
child: const Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.add, size: 24, color: ColorPalette.primary),
|
||||||
|
SizedBox(width: 12,),
|
||||||
|
Text('New Bank',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Save',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
provider.setCurrentAcc(provider.selectedAccount!);
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardAccount(Account account, String numberSelected) {
|
||||||
|
List<String> listNumber = [];
|
||||||
|
|
||||||
|
List.generate(account.number.length, (index) {
|
||||||
|
if(index > 3 && index < account.number.length - 4){
|
||||||
|
listNumber.add('*');
|
||||||
|
}else{
|
||||||
|
listNumber.add(account.number[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(account.nameOwner,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${account.nameBank} - ${listNumber.join("")}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
margin: const EdgeInsets.only(top: 4),
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: numberSelected == account.number
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate200)),
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
numberSelected == account.number ? ColorPalette.primary : ColorPalette.white,
|
||||||
|
shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,361 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class RedeemProduct extends StatefulWidget {
|
||||||
|
const RedeemProduct({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RedeemProduct> createState() => _RedeemProductState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RedeemProductState extends State<RedeemProduct> {
|
||||||
|
TextEditingController amountController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// TODO: implement initState
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
super.dispose();
|
||||||
|
amountController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
double amount = provider.getAmount ?? provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!;
|
||||||
|
amountController.text = NumberFormatter.numberCurrency(amount.toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Products to be Redeemed',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
cardProduct(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
segmentAmount(
|
||||||
|
context,
|
||||||
|
provider.getAmount ?? provider.getCurrentProduct.priceUnit! * (provider.getCurrentProduct.totalUnit! / 2.0),
|
||||||
|
provider.getUnit ?? provider.getCurrentProduct.totalUnit! / 2.0,
|
||||||
|
(value) {
|
||||||
|
provider.setUnit(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
segmentDestinationAcc(provider.getCurrentAccount),
|
||||||
|
const SizedBox(height: 36),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Redeem',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return TotalRedeem();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct() {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Money Market' ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor['Money Market'],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget segmentAmount(context, double currentAmount, double currentUnit, void Function(double value) setUnit) {
|
||||||
|
double sliderValue = currentUnit / Provider.of<RedeemProductViewModel>(context, listen: false).getCurrentProduct.totalUnit!;
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text('Amount',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
controller: amountController,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: ColorPalette.slate200,
|
||||||
|
width: 1
|
||||||
|
),
|
||||||
|
),
|
||||||
|
suffixIcon: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return ChangeAmount(
|
||||||
|
totalAmount: currentAmount.toInt(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.edit, color: ColorPalette.primary),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text(' unit',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SliderTheme(
|
||||||
|
data: SliderTheme.of(context).copyWith(
|
||||||
|
trackHeight: 4.0,
|
||||||
|
thumbColor: ColorPalette.primary,
|
||||||
|
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10.0),
|
||||||
|
overlayColor:Colors.deepPurple,
|
||||||
|
inactiveTickMarkColor: ColorPalette.primary,
|
||||||
|
inactiveTrackColor: ColorPalette.slate200,
|
||||||
|
overlayShape: SliderComponentShape.noOverlay
|
||||||
|
),
|
||||||
|
child: Slider(
|
||||||
|
value: sliderValue,
|
||||||
|
onChanged: setUnit,
|
||||||
|
label: sliderValue.round().toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Text('${(sliderValue * 100).toStringAsFixed(2)} %',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget segmentDestinationAcc(Account account) {
|
||||||
|
List<String> listNumber = [];
|
||||||
|
|
||||||
|
List.generate(account.number.length, (index) {
|
||||||
|
if(index > 3 && index < account.number.length - 4){
|
||||||
|
listNumber.add('*');
|
||||||
|
}else{
|
||||||
|
listNumber.add(account.number[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Destination Account',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(account.nameOwner,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('${account.nameBank} - ${listNumber.join("")}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) => const ChangeDestinationAccount(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
color: ColorPalette.blue200.withOpacity(0.5)
|
||||||
|
),
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text('Change',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/radio_agreement.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class TotalRedeem extends StatelessWidget {
|
||||||
|
const TotalRedeem({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Investment Funds that You Cash Out',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: cardProduct(provider.getCurrentProduct, provider.getUnit!),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Sales Commission',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Free',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Cash Out Method',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Regular',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16,),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
color: ColorPalette.slate200.withOpacity(0.5),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextTitle(
|
||||||
|
title: 'Estimated Funds Disbursed',
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
fontSize: 16,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RadioAgreement(
|
||||||
|
isAgree: provider.isAgree,
|
||||||
|
desc: 'I agree to the sale of the mutual funds listed on this page. I understand that the total funds disbursed are approximate. The amount received may change according to the closing price of the mutual fund on the day of sale.',
|
||||||
|
onTap: provider.setAgree
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
ButtonView(
|
||||||
|
disabled: !provider.isAgree,
|
||||||
|
name: 'Redeem',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
||||||
|
textColor: !provider.isAgree ? ColorPalette.slate400 : Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return TotalRedeem();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct(PortfolioProduct product, double currentUnit) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: product.name ?? '', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text(' unit',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Account {
|
||||||
|
String nameOwner, nameBank, number;
|
||||||
|
|
||||||
|
Account(this.nameOwner, this.nameBank, this.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PortfolioProduct {
|
||||||
|
String? name, type;
|
||||||
|
double? yield;
|
||||||
|
double? priceUnit, funds, totalPercent, totalUnit;
|
||||||
|
|
||||||
|
PortfolioProduct({this.name, this.type, this.yield, this.priceUnit, this.funds, this.totalPercent = 1, this.totalUnit});
|
||||||
|
}
|
||||||
|
|
||||||
|
class RedeemProductViewModel extends ChangeNotifier {
|
||||||
|
static Account currentAccount = Account('Muhamad Rosyidin', 'BRI', '902139012324');
|
||||||
|
static PortfolioProduct currentProduct =
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000,
|
||||||
|
totalUnit: 25
|
||||||
|
);
|
||||||
|
|
||||||
|
static double? amount;
|
||||||
|
static double? unit;
|
||||||
|
Account? selectedAccount;
|
||||||
|
|
||||||
|
Account get getCurrentAccount => currentAccount;
|
||||||
|
PortfolioProduct get getCurrentProduct => currentProduct;
|
||||||
|
double? get getAmount => amount;
|
||||||
|
double? get getUnit => unit;
|
||||||
|
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
|
void setCurrentAcc(Account account) {
|
||||||
|
currentAccount = account;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSelectedAcc(Account account){
|
||||||
|
selectedAccount = account;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAmount(double amount) {
|
||||||
|
amount = amount;
|
||||||
|
unit = (amount / currentProduct.priceUnit!);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnit(double value){
|
||||||
|
unit = currentProduct.totalUnit! * value;
|
||||||
|
amount = unit! * currentProduct.priceUnit!;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProduct(PortfolioProduct product) {
|
||||||
|
currentProduct = product;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,8 +24,9 @@ class Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProductView extends StatefulWidget {
|
class ProductView extends StatefulWidget {
|
||||||
final String investType;
|
final bool seeMore;
|
||||||
const ProductView(this.investType, {super.key});
|
final Product selectedProduct;
|
||||||
|
const ProductView({super.key, required this.selectedProduct, this.seeMore = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProductView> createState() => _ProductViewState();
|
State<ProductView> createState() => _ProductViewState();
|
||||||
|
@ -144,22 +145,23 @@ class _ProductViewState extends State<ProductView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomNavigationBar: Container(
|
bottomNavigationBar: !widget.seeMore ?
|
||||||
height: SizeConfig.height * .1,
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
height: SizeConfig.height * .1,
|
||||||
child: ButtonView(
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
name: 'Subscribe',
|
child: ButtonView(
|
||||||
onPressed: () {
|
name: 'Subscribe',
|
||||||
showModalBottomSheet(
|
onPressed: () {
|
||||||
context: context,
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
context: context,
|
||||||
builder: (context) => SelectGoalInvesting(),
|
isScrollControlled: true,
|
||||||
);
|
builder: (context) => SelectGoalInvesting(),
|
||||||
},
|
);
|
||||||
height: SizeConfig.height * 0.06,
|
},
|
||||||
marginVertical: 16,
|
height: SizeConfig.height * 0.06,
|
||||||
),
|
marginVertical: 16,
|
||||||
),
|
),
|
||||||
|
) : SizedBox(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +179,7 @@ class _ProductViewState extends State<ProductView> {
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Gemilang Dana Kas Maxima',
|
widget.selectedProduct.name ?? '',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -190,17 +192,18 @@ class _ProductViewState extends State<ProductView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(6),
|
padding: const EdgeInsets.all(6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(40),
|
borderRadius: BorderRadius.circular(40),
|
||||||
color: ColorPalette.investTypeBgColor[widget.investType] ?? Colors.white,
|
color: ColorPalette.investTypeBgColor[widget.selectedProduct.type] ?? Colors.white,
|
||||||
border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.investType] ?? Colors.white)
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.selectedProduct.type] ?? Colors.white)
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.investType,
|
widget.selectedProduct.type ?? '',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.investTypeColor[widget.investType],
|
color: ColorPalette.investTypeColor[widget.selectedProduct.type],
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cims_apps/application/component/subscribe/goal_investing_view.da
|
||||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -11,10 +12,9 @@ class SelectGoalInvesting extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiProvider(
|
|
||||||
providers: [
|
return ChangeNotifierProvider(
|
||||||
ChangeNotifierProvider(create: (context) => ProductViewModel(),)
|
create: (context) => ProductViewModel(),
|
||||||
],
|
|
||||||
child: Consumer<ProductViewModel>(
|
child: Consumer<ProductViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Container(
|
return Container(
|
||||||
|
@ -51,23 +51,39 @@ class SelectGoalInvesting extends StatelessWidget {
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return InputInvestmentView(
|
return ChangeNotifierProvider(
|
||||||
selectedPlan: p0,
|
create: (context) => ProductViewModel(),
|
||||||
nextMove: (value) {
|
child: Consumer<ProductViewModel>(
|
||||||
Navigator.pop(context);
|
builder: (context, provider, child) {
|
||||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
return InputInvestmentView(
|
||||||
showModalBottomSheet(
|
selectedPlan: p0,
|
||||||
context: context,
|
nextMove: (value) {
|
||||||
isScrollControlled: true,
|
Navigator.pop(context);
|
||||||
builder: (context) =>
|
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
||||||
TotalPaymentView(
|
showModalBottomSheet(
|
||||||
listProduct: [
|
context: context,
|
||||||
provider.getSelectedProduct
|
isScrollControlled: true,
|
||||||
],
|
builder: (context) =>
|
||||||
totalInvest: formatIntParse,
|
ChangeNotifierProvider(
|
||||||
)
|
create: (context) => ProductViewModel(),
|
||||||
);
|
child: Consumer<ProductViewModel>(
|
||||||
},
|
builder: (context, provider, child) {
|
||||||
|
return TotalPaymentView(
|
||||||
|
listProduct: [
|
||||||
|
provider.getSelectedProduct
|
||||||
|
],
|
||||||
|
totalInvest: formatIntParse,
|
||||||
|
isAgree: provider.isAgree,
|
||||||
|
onTapAgree: provider.setAgree,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,6 +14,7 @@ class ProductViewModel extends ChangeNotifier {
|
||||||
Product get getSelectedProduct => selectedProduct;
|
Product get getSelectedProduct => selectedProduct;
|
||||||
|
|
||||||
double totalInvestment = 0;
|
double totalInvestment = 0;
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
void setSelectedProduct(Product product) {
|
void setSelectedProduct(Product product) {
|
||||||
selectedProduct = product;
|
selectedProduct = product;
|
||||||
|
@ -24,4 +25,9 @@ class ProductViewModel extends ChangeNotifier {
|
||||||
totalInvestment = value;
|
totalInvestment = value;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ class ProfileView extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(height: SizeConfig.height * .1, title: 'Profile'),
|
appBar: CustomAppBar(height: SizeConfig.height * .08, title: 'Profile'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ class TransactionView extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar:
|
appBar: CustomAppBar(height: SizeConfig.height * 0.08, title: 'Transaction'),
|
||||||
CustomAppBar(height: SizeConfig.height * .1, title: 'Transaction'),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user