Compare commits
22 Commits
6a43a3dcaf
...
yoga
Author | SHA1 | Date | |
---|---|---|---|
e441c56bab | |||
e513df325c | |||
23e1a6628f | |||
4b07219928 | |||
9cdda42b8b | |||
6f5d3ccca8 | |||
eb99ad9d7f | |||
ff515e2621 | |||
f057a346c2 | |||
f84fe1017d | |||
27ba55314b | |||
59e046bd92 | |||
4461b78565 | |||
f2f688f9f3 | |||
d1adfd2ab0 | |||
33b2ab85e3 | |||
a87afe16cb | |||
1904e9a4a3 | |||
d79959c47f | |||
38837bd4f8 | |||
d966108e9e | |||
506f364b87 |
BIN
assets/icons/icon-card.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/icons/icon-cat.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
assets/icons/icon-education.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/icons/icon-faqs.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/icons/icon-fund.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/icons/icon-gadget-outline.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/icon-home.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/icon-logout.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/icons/icon-padlock.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/icons/icon-profile.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/icons/icon-setting.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/icons/icon-shop.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/images/img-dashboard-profile.png
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/images/img-empty-transaction.png
Normal file
After Width: | Height: | Size: 70 KiB |
@@ -49,12 +49,30 @@ class PathAssets {
|
||||
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
||||
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
||||
static const String iconCar = 'assets/icons/icon-car.png';
|
||||
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 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';
|
||||
static const String iconCat = 'assets/icons/icon-cat.png';
|
||||
static const String iconProfile = 'assets/icons/icon-profile.png';
|
||||
static const String iconPadlock = 'assets/icons/icon-padlock.png';
|
||||
static const String iconCard = 'assets/icons/icon-card.png';
|
||||
static const String iconSetting = 'assets/icons/icon-setting.png';
|
||||
static const String iconFaqs = 'assets/icons/icon-faqs.png';
|
||||
static const String iconLogout = 'assets/icons/icon-logout.png';
|
||||
static const String iconEducation = 'assets/icons/icon-education.png';
|
||||
static const String iconFund = 'assets/icons/icon-fund.png';
|
||||
static const String iconHome = 'assets/icons/icon-home.png';
|
||||
static const String iconShop = 'assets/icons/icon-shop.png';
|
||||
static const String iconGadgetOutline =
|
||||
'assets/icons/icon-gadget-outline.png';
|
||||
|
||||
/// IMAGE
|
||||
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
||||
@@ -89,9 +107,14 @@ class PathAssets {
|
||||
static const String imgGuide1 = 'assets/images/img-guide1.png';
|
||||
static const String imgGuide2 = 'assets/images/img-guide2.png';
|
||||
static const String imgOpenShopping = 'assets/images/img-open-shopping.png';
|
||||
static const String imgPaymentSuccess = 'assets/images/img-payment-success.png';
|
||||
static const String imgPaymentSuccess =
|
||||
'assets/images/img-payment-success.png';
|
||||
static const String frameSignature = 'assets/images/frame-signature.png';
|
||||
static const String imgFinish = 'assets/images/img-finish.png';
|
||||
static const String imgDashboardProfile =
|
||||
'assets/images/img-dashboard-profile.png';
|
||||
static const String imgEmptyTransaction =
|
||||
'assets/images/img-empty-transaction.png';
|
||||
|
||||
static const Map<String, String> goalInvestIcon = {
|
||||
'Education': iconToga,
|
||||
|
@@ -0,0 +1,100 @@
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CardTransactionView extends StatelessWidget {
|
||||
final VoidCallback onTap;
|
||||
final String iconPath, type, amount, subs, step;
|
||||
final String? timeTransaction;
|
||||
const CardTransactionView({
|
||||
Key? key,
|
||||
required this.step,
|
||||
required this.type,
|
||||
required this.amount,
|
||||
required this.iconPath,
|
||||
required this.subs,
|
||||
required this.onTap,
|
||||
this.timeTransaction,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextTheme textTheme = Theme.of(context).textTheme;
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: SizeConfig.width * .4,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
ImageView(
|
||||
image: iconPath, width: SizeConfig.width * .12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
type,
|
||||
style: textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Text(
|
||||
amount,
|
||||
style: textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
SizedBox(
|
||||
width: SizeConfig.width * .4,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: SizeConfig.height * .08,
|
||||
child: Text(
|
||||
subs,
|
||||
style: const TextStyle(color: ColorPalette.primary),
|
||||
)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
step == 'waiting'
|
||||
? const Icon(Icons.access_time_sharp,
|
||||
color: ColorPalette.slate400)
|
||||
: const SizedBox(),
|
||||
step == 'waiting'
|
||||
? Text(timeTransaction.toString())
|
||||
: const SizedBox(),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 16.0),
|
||||
child: Icon(Icons.arrow_forward_ios),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
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/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class EmptyCardTransaction extends StatelessWidget {
|
||||
final VoidCallback onPressedButton;
|
||||
const EmptyCardTransaction({Key? key, required this.onPressedButton})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextTheme textTheme = Theme.of(context).textTheme;
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
ImageView(
|
||||
image: PathAssets.imgEmptyTransaction,
|
||||
width: SizeConfig.width * .4,
|
||||
),
|
||||
Text(
|
||||
'No Transaction Yet',
|
||||
style: textTheme.headlineSmall,
|
||||
),
|
||||
Text(
|
||||
"Let's keep building your investment for even greater financial growth!",
|
||||
style: textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
ButtonView(
|
||||
name: 'Investing Now',
|
||||
width: SizeConfig.width * .5,
|
||||
onPressed: onPressedButton,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,119 @@
|
||||
import 'package:cims_apps/application/component/expandable_widget/see_more_less_widget.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ExpandableWidget extends StatelessWidget {
|
||||
final String? content;
|
||||
final double? fontSize;
|
||||
final int maxLinesToShow;
|
||||
final Alignment? alignmentMore;
|
||||
final bool? hideTextMore;
|
||||
final bool? hideIconMore;
|
||||
|
||||
ExpandableWidget({
|
||||
super.key,
|
||||
required this.content,
|
||||
this.fontSize,
|
||||
this.maxLinesToShow = 1,
|
||||
this.alignmentMore,
|
||||
this.hideTextMore = false,
|
||||
this.hideIconMore = true,
|
||||
});
|
||||
|
||||
ValueNotifier<bool> expanded = ValueNotifier(false);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TextSpan textSpan = TextSpan(
|
||||
text: content ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? 16.0,
|
||||
color: ColorPalette.slate400,
|
||||
),
|
||||
);
|
||||
|
||||
final TextPainter textPainter = TextPainter(
|
||||
text: textSpan,
|
||||
maxLines: expanded.value ? null : maxLinesToShow,
|
||||
textDirection: TextDirection.ltr,
|
||||
strutStyle: StrutStyle(
|
||||
fontSize: fontSize ?? 16.0,
|
||||
)
|
||||
);
|
||||
|
||||
textPainter.layout(maxWidth: SizeConfig.width);
|
||||
|
||||
final int numberOfLines = textPainter.computeLineMetrics().length;
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: expanded,
|
||||
builder: (context, values, _) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
if (!expanded.value && numberOfLines >= maxLinesToShow) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
content ?? "",
|
||||
maxLines: maxLinesToShow,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? 16.0,
|
||||
color: ColorPalette.slate400,
|
||||
),
|
||||
),
|
||||
/* See More :: type 1 - See More | 2 - See Less */
|
||||
SeeMoreLessWidget(
|
||||
textData: 'See More',
|
||||
type: 1,
|
||||
section: 1,
|
||||
onSeeMoreLessTap: () {
|
||||
expanded.value = true;
|
||||
},
|
||||
alignment: alignmentMore,
|
||||
hideIconMore: hideIconMore!,
|
||||
hideTextMore: hideTextMore!,
|
||||
),
|
||||
/* See More :: type 1 - See More | 2 - See Less */
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
content ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? 16.0,
|
||||
color: ColorPalette.slate400,
|
||||
),
|
||||
),
|
||||
if (expanded.value && numberOfLines >= maxLinesToShow)
|
||||
/* See Less :: type 1 - See More | 2 - See Less */
|
||||
SeeMoreLessWidget(
|
||||
textData: 'See Less',
|
||||
type: 2,
|
||||
section: 1,
|
||||
onSeeMoreLessTap: () {
|
||||
expanded.value = false;
|
||||
},
|
||||
alignment: alignmentMore,
|
||||
hideIconMore: hideIconMore!,
|
||||
hideTextMore: hideTextMore!,
|
||||
),
|
||||
/* See Less :: type 1 - See More | 2 - See Less */
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SeeMoreLessWidget extends StatelessWidget {
|
||||
final String? textData;
|
||||
final int? type; /* type 1 - See More | 2 - See Less */
|
||||
final Function? onSeeMoreLessTap;
|
||||
final int?
|
||||
section; /* 1: About the course | 2 - Who can take up this course? | 3 - Mentors | 4 - Course Video Reviews */
|
||||
final Alignment? alignment;
|
||||
final bool hideTextMore;
|
||||
final bool hideIconMore;
|
||||
|
||||
const SeeMoreLessWidget({
|
||||
super.key,
|
||||
required this.textData,
|
||||
required this.type,
|
||||
required this.onSeeMoreLessTap,
|
||||
required this.section,
|
||||
required this.alignment,
|
||||
required this.hideTextMore,
|
||||
required this.hideIconMore,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
alignment: alignment ?? Alignment.centerLeft,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (onSeeMoreLessTap != null) {
|
||||
onSeeMoreLessTap!();
|
||||
}
|
||||
},
|
||||
child: Text.rich(
|
||||
softWrap: true,
|
||||
style: const TextStyle(
|
||||
color: ColorPalette.primary,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
TextSpan(
|
||||
text: "",
|
||||
children: [
|
||||
if(!hideTextMore)
|
||||
TextSpan(
|
||||
text: textData,
|
||||
style: const TextStyle(
|
||||
color: ColorPalette.primary,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
if(!hideTextMore && !hideIconMore)
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 3.0,
|
||||
),
|
||||
),
|
||||
if(!hideIconMore)
|
||||
WidgetSpan(
|
||||
child: Icon(
|
||||
(type == 1)
|
||||
? Icons.keyboard_arrow_down
|
||||
: Icons.keyboard_arrow_up,
|
||||
color: ColorPalette.slate300,
|
||||
size: 28,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,5 +1,3 @@
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -86,7 +84,7 @@ class NumericPad extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget spaceWidget() {
|
||||
return Expanded(
|
||||
return const Expanded(
|
||||
child: SizedBox()
|
||||
);
|
||||
}
|
||||
@@ -98,11 +96,12 @@ class NumericPad extends StatelessWidget {
|
||||
onNumberSelected(number);
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.symmetric(vertical: SizeConfig.height * .028),
|
||||
child: Text(
|
||||
number,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorPalette.slate800
|
||||
@@ -119,11 +118,15 @@ class NumericPad extends StatelessWidget {
|
||||
onTap: () {
|
||||
onNumberSelected('');
|
||||
},
|
||||
child: Icon(
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.symmetric(vertical: SizeConfig.height * .028),
|
||||
child: const Icon(
|
||||
Icons.backspace_outlined,
|
||||
size: 28,
|
||||
color: ColorPalette.slate800,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -44,28 +45,11 @@ class RadioAgreement extends StatelessWidget {
|
||||
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),
|
||||
))
|
||||
],
|
||||
))
|
||||
child: ExpandableWidget(
|
||||
content: desc,
|
||||
maxLinesToShow: 3,
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
||||
@@ -73,20 +74,20 @@ class RiskProfile extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(24),
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
riskProfile.type,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
color: ColorPalette.white
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16,),
|
||||
Text('Total Score :',
|
||||
const SizedBox(height: 16,),
|
||||
const Text('Total Score :',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
@@ -94,7 +95,7 @@ class RiskProfile extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text('$totalScore',
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 28,
|
||||
color: ColorPalette.white
|
||||
@@ -107,20 +108,20 @@ class RiskProfile extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Text(
|
||||
riskProfile.desc,
|
||||
style: TextStyle(
|
||||
color: ColorPalette.slate500,
|
||||
fontSize: 16
|
||||
)
|
||||
ExpandableWidget(
|
||||
content: riskProfile.desc,
|
||||
hideTextMore: true,
|
||||
hideIconMore: false,
|
||||
maxLinesToShow: 4,
|
||||
alignmentMore: Alignment.center,
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Text(
|
||||
const Text(
|
||||
'Suitable Product',
|
||||
style: TextStyle(
|
||||
color: ColorPalette.slate800,
|
||||
@@ -128,7 +129,7 @@ class RiskProfile extends StatelessWidget {
|
||||
fontSize: 18
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
rowSuitableProduct ?
|
||||
@@ -137,7 +138,7 @@ class RiskProfile extends StatelessWidget {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0),
|
||||
padding: EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: ColorPalette.slate200),
|
||||
borderRadius: BorderRadius.circular(6)
|
||||
@@ -146,18 +147,18 @@ class RiskProfile extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: riskProfile.color.withOpacity(0.1)
|
||||
),
|
||||
child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text(e.value['desc'],
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorPalette.slate800
|
||||
@@ -173,7 +174,7 @@ class RiskProfile extends StatelessWidget {
|
||||
runSpacing: 16,
|
||||
children: riskProfile.suitableProduct.map((e) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(color: ColorPalette.slate200),
|
||||
@@ -181,7 +182,7 @@ class RiskProfile extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(8),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
@@ -189,12 +190,12 @@ class RiskProfile extends StatelessWidget {
|
||||
),
|
||||
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(e['desc'],
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorPalette.slate800
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
@@ -6,9 +8,13 @@ import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class InputInvestmentView extends StatefulWidget {
|
||||
final String selectedPlan;
|
||||
final String? currentPlan;
|
||||
final void Function()? changePlan;
|
||||
final int? currentPrice;
|
||||
final int? minimumPrice;
|
||||
final int? maximumPrice;
|
||||
final void Function(String value) nextMove;
|
||||
const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove});
|
||||
const InputInvestmentView({super.key, required this.nextMove, this.currentPlan, this.minimumPrice, this.maximumPrice, this.currentPrice, this.changePlan});
|
||||
|
||||
@override
|
||||
State<InputInvestmentView> createState() => _InputInvestmentViewState();
|
||||
@@ -17,10 +23,35 @@ class InputInvestmentView extends StatefulWidget {
|
||||
class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
TextEditingController inputController = TextEditingController();
|
||||
|
||||
void validationInputValue(String currentValue) {
|
||||
currentValue = currentValue.replaceAll('Rp ', '').replaceAll('.', '');
|
||||
if(currentValue.isEmpty){
|
||||
currentValue = '0';
|
||||
}
|
||||
double parseValue = double.parse(currentValue);
|
||||
if(widget.minimumPrice != null){
|
||||
if(parseValue <= widget.minimumPrice!){
|
||||
parseValue = widget.minimumPrice!.toDouble();
|
||||
}
|
||||
}
|
||||
|
||||
if(widget.maximumPrice != null){
|
||||
if(parseValue >= widget.maximumPrice!){
|
||||
parseValue = widget.maximumPrice!.toDouble();
|
||||
}
|
||||
}
|
||||
|
||||
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
if(widget.currentPrice != null){
|
||||
inputController.text = NumberFormatter.numberCurrency(widget.currentPrice, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
}else{
|
||||
inputController.text = 'Rp 0';
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -41,22 +72,25 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if(widget.currentPlan != null)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(widget.selectedPlan,
|
||||
style: TextStyle(
|
||||
Text(widget.currentPlan ?? '',
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: widget.changePlan,
|
||||
child: const Row(
|
||||
children: [
|
||||
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
||||
SizedBox(width: 4),
|
||||
@@ -68,28 +102,23 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
TextField(
|
||||
controller: inputController,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
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){
|
||||
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
}else{
|
||||
inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
}
|
||||
validationInputValue(value);
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
decoration: const InputDecoration(
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: ColorPalette.primary,
|
||||
@@ -98,30 +127,36 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text('Minimum Budget Rp1,000,000',
|
||||
style: TextStyle(
|
||||
const SizedBox(height: 12),
|
||||
if(widget.minimumPrice != null)
|
||||
Text('Minimum ${NumberFormatter.numberCurrency(widget.minimumPrice, 'Rp ', 'id_ID')}',
|
||||
style: const TextStyle(
|
||||
color: ColorPalette.slate400,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
if(widget.maximumPrice != null)
|
||||
Text('Maximum ${NumberFormatter.numberCurrency(widget.maximumPrice, 'Rp ', 'id_ID')}',
|
||||
style: const TextStyle(
|
||||
color: ColorPalette.slate400,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
NumericPad(onNumberSelected: (p0) {
|
||||
String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', '');
|
||||
String getNumeric = p0;
|
||||
String currentValue = inputController.text;
|
||||
if(p0.isNotEmpty){
|
||||
if(checkIsZeroInput != '0'){
|
||||
getNumeric = checkIsZeroInput + getNumeric;
|
||||
if(currentValue != '0'){
|
||||
currentValue = currentValue + p0;
|
||||
}
|
||||
}else{
|
||||
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
|
||||
currentValue = currentValue.substring(0, currentValue.length - 1);
|
||||
}
|
||||
String formatNumeric = NumberFormatter.numberCurrency(
|
||||
double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
|
||||
inputController.text = formatNumeric;
|
||||
validationInputValue(currentValue);
|
||||
}),
|
||||
SizedBox(height: 8),
|
||||
const SizedBox(height: 24),
|
||||
ButtonView(
|
||||
name: 'Next',
|
||||
onPressed: () {
|
||||
@@ -129,7 +164,7 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
},
|
||||
width: SizeConfig.width,
|
||||
heightWrapContent: true,
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
marginVertical: 0,
|
||||
)
|
||||
],
|
||||
@@ -137,6 +172,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||
),
|
||||
],
|
||||
),
|
||||
);;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -139,9 +139,8 @@ class TotalPaymentView extends StatelessWidget {
|
||||
),
|
||||
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',
|
||||
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.',
|
||||
onTap: () {
|
||||
print('gagaga');
|
||||
onTapAgree();
|
||||
},
|
||||
),
|
||||
|
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/component/take_picture_screen/take_picture_screen.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
@@ -94,10 +95,8 @@ class _DisplayPictureScreenState extends State<DisplayPictureScreen> {
|
||||
return Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Preview'),
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
appBar: CustomAppBar(
|
||||
height: SizeConfig.height * .08, title: 'Preview'),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Column(
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart';
|
||||
import 'package:cims_apps/core/route/route.dart';
|
||||
@@ -27,7 +28,6 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
||||
late String _takeContent;
|
||||
|
||||
Future<void> changeFlash() async {
|
||||
await _controller.setFlashMode(FlashMode.auto);
|
||||
setState(() {
|
||||
isFlash = !isFlash;
|
||||
});
|
||||
@@ -44,6 +44,7 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
||||
// Next, initialize the controller. This returns a Future.
|
||||
_initializeControllerFuture = _controller.initialize();
|
||||
_takeContent = widget.takeContent;
|
||||
_controller.setFlashMode(isFlash ? FlashMode.torch : FlashMode.off);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -57,9 +58,10 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
// Fill this out in the next steps.
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Registration'),
|
||||
actions: [
|
||||
appBar: CustomAppBar(
|
||||
title: 'Registration',
|
||||
height: SizeConfig.height * .08,
|
||||
trailing: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
changeFlash();
|
||||
|
@@ -190,6 +190,18 @@ class TextFormView extends StatelessWidget {
|
||||
color: focusedBorderColor ?? ColorPalette.greyBorder,
|
||||
),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: _borderRadius,
|
||||
borderSide: BorderSide(
|
||||
color: ColorPalette.red600
|
||||
)
|
||||
),
|
||||
focusedErrorBorder: OutlineInputBorder(
|
||||
borderRadius: _borderRadius,
|
||||
borderSide: BorderSide(
|
||||
color: ColorPalette.red600
|
||||
)
|
||||
),
|
||||
border: OutlineInputBorder(borderRadius: _borderRadius),
|
||||
suffixIcon: suffixIcon,
|
||||
prefixIcon: prefixIcon,
|
||||
|
@@ -5,17 +5,20 @@ class TextTitle extends StatelessWidget {
|
||||
final String title;
|
||||
final Color? color;
|
||||
final double? fontSize;
|
||||
final TextAlign? textAlign;
|
||||
const TextTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
this.color,
|
||||
this.fontSize,
|
||||
this.textAlign,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
textAlign: textAlign,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
|
@@ -75,6 +75,7 @@ class ColorPalette {
|
||||
static const Color backgroundBlueLight = Color(0xFFEBF3FD);
|
||||
static const Color blue50 = Color(0xFFEFF6FF);
|
||||
static const Color blue200 = Color(0xFFBFDBFE);
|
||||
static const Color blue600 = Color(0xFF2563EB);
|
||||
static const Color blue900 = Color(0xFF1E3A8A);
|
||||
static const Color slate50 = Color(0xFFF8FAFC);
|
||||
static const Color slate200 = Color(0xFFE2E8F0);
|
||||
@@ -90,9 +91,11 @@ class ColorPalette {
|
||||
static const Color cyan100 = Color(0xFFCFFAFE);
|
||||
static const Color cyan500 = Color(0xFF06B6D4);
|
||||
static const Color green100 = Color(0xFFDCFCE7);
|
||||
static const Color green300 = Color(0xFF86EFAC);
|
||||
static const Color green400 = Color(0xFF4ADE80);
|
||||
static const Color green500 = Color(0xFF16A34A);
|
||||
static const Color red600 = Color(0xffDC2626);
|
||||
static const Color red600 = Color(0xFFDC2626);
|
||||
static const Color red50 = Color(0xFFFEF2F2);
|
||||
|
||||
static const Map<String, Color> investTypeColor = {
|
||||
'Money Market': purple500,
|
||||
@@ -107,4 +110,16 @@ class ColorPalette {
|
||||
'Sharia': green100,
|
||||
'Bonds': cyan100
|
||||
};
|
||||
|
||||
static const Map<String, Color> riskColor = {
|
||||
'Moderate': orange500,
|
||||
'Conservative': green500,
|
||||
'Aggressive': cyan500
|
||||
};
|
||||
|
||||
static const Map<String, Color> textRiskColor = {
|
||||
'Moderate': orange500,
|
||||
'Conservative': green300,
|
||||
'Aggressive': cyan500
|
||||
};
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class StringUtils {
|
||||
static bool emailValidation(String email) {
|
||||
return RegExp(
|
||||
@@ -13,4 +15,12 @@ class StringUtils {
|
||||
return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})')
|
||||
.hasMatch(password);
|
||||
}
|
||||
|
||||
static String formatTime(DateTime? dateTime) {
|
||||
if (dateTime != null) {
|
||||
DateFormat formatter = DateFormat('HH:mm:ss');
|
||||
return formatter.format(dateTime);
|
||||
}
|
||||
return '--:--:--';
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ class PhoneNumberView extends StatelessWidget {
|
||||
width: SizeConfig.width * .23,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
margin: const EdgeInsets.only(right: 16),
|
||||
margin: const EdgeInsets.only(right: 16, left: 1, top: 1, bottom: 1),
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorPalette.grey,
|
||||
borderRadius: BorderRadius.only(
|
||||
|
@@ -6,19 +6,26 @@ import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/route/route.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ModelDataBank {
|
||||
final String? title, subtitle;
|
||||
ModelDataBank(this.title, this.subtitle);
|
||||
}
|
||||
|
||||
class ConfirmBankAccount extends StatelessWidget {
|
||||
const ConfirmBankAccount({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List listData = [
|
||||
{'title': 'Bank Name', 'subtitle': 'Bank Mandiri'},
|
||||
{'title': 'Account Number', 'subtitle': '123002212084'},
|
||||
{'title': 'Account Owner Name', 'subtitle': 'Muhamad Rosyidin'},
|
||||
{'title': 'Name on ID card', 'subtitle': 'Muhamad Rosyidin'},
|
||||
];
|
||||
final listDataBank =
|
||||
ModalRoute.of(context)!.settings.arguments as List<ModelDataBank>;
|
||||
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => SubmissionDataViewModel(),
|
||||
builder: (context, child) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 70,
|
||||
@@ -42,7 +49,9 @@ class ConfirmBankAccount extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SizedBox(
|
||||
height: SizeConfig.height * .85,
|
||||
child: Column(
|
||||
child: Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -53,7 +62,7 @@ class ConfirmBankAccount extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
...listData.map((e) {
|
||||
...listDataBank.map((e) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: Column(
|
||||
@@ -61,12 +70,13 @@ class ConfirmBankAccount extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
e['title'],
|
||||
e.title!,
|
||||
style: const TextStyle(
|
||||
color: ColorPalette.slate400, fontSize: 16),
|
||||
color: ColorPalette.slate400,
|
||||
fontSize: 16),
|
||||
),
|
||||
Text(
|
||||
e['subtitle'],
|
||||
e.subtitle!,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: ColorPalette.slate800,
|
||||
@@ -98,15 +108,18 @@ class ConfirmBankAccount extends StatelessWidget {
|
||||
name: 'Confirm',
|
||||
width: SizeConfig.width * .42,
|
||||
onPressed: () {
|
||||
routePush(context, page: const SubmissionParent());
|
||||
routePush(context,
|
||||
page: const SubmissionParent());
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -63,9 +63,13 @@ class SubmitBankAccount extends StatelessWidget {
|
||||
return SizedBox(
|
||||
child: Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return SingleChildScrollView(
|
||||
return SizedBox(
|
||||
height: SizeConfig.height * .8,
|
||||
child: Form(
|
||||
key: provider.formKeySubmitDataBank,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const TextCaption(title: 'Input your bank account data'),
|
||||
TextFormView(
|
||||
@@ -79,11 +83,24 @@ class SubmitBankAccount extends StatelessWidget {
|
||||
suffixIcon: const Icon(
|
||||
Icons.keyboard_arrow_down_outlined,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormView(
|
||||
name: 'Account Number',
|
||||
hintText: 'Input Account Number',
|
||||
ctrl: provider.ctrlNoAccountBank,
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
trailingTitleWidget: SizedBox(
|
||||
width: 24,
|
||||
child: GestureDetector(
|
||||
@@ -98,6 +115,13 @@ class SubmitBankAccount extends StatelessWidget {
|
||||
TextFormView(
|
||||
name: 'Account Owner Name',
|
||||
hintText: 'Input Account Name',
|
||||
ctrl: provider.ctrlNameAccountBank,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const Text(
|
||||
"Make sure the account you use is in your name, not someone else's",
|
||||
@@ -109,16 +133,29 @@ class SubmitBankAccount extends StatelessWidget {
|
||||
ButtonView(
|
||||
name: 'Next',
|
||||
onPressed: () {
|
||||
if (provider.formKeySubmitDataBank.currentState!
|
||||
.validate()) {
|
||||
provider
|
||||
.submitDataBank(
|
||||
bankName: provider.ctrlBankName.text,
|
||||
accountNumber: provider.ctrlNoAccountBank.text,
|
||||
accountName: provider.ctrlNameAccountBank.text,
|
||||
)
|
||||
.then((values) {
|
||||
provider.next(context).then((value) {
|
||||
if (value) {
|
||||
routePush(context,
|
||||
page: const ConfirmBankAccount());
|
||||
page: const ConfirmBankAccount(),
|
||||
arguments: values);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@@ -14,12 +14,12 @@ class RiskProfileView extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: SizeConfig.width,
|
||||
height: SizeConfig.height,
|
||||
padding: EdgeInsets.all(24),
|
||||
height: SizeConfig.height * .8,
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
const Column(
|
||||
children: [
|
||||
ImageView(image: PathAssets.imgDataReport),
|
||||
SizedBox(
|
||||
@@ -48,7 +48,7 @@ class RiskProfileView extends StatelessWidget {
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ImageView(
|
||||
@@ -68,7 +68,7 @@ class RiskProfileView extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
ButtonView(
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/route/route.dart';
|
||||
@@ -66,21 +67,33 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => SubmissionDataViewModel(),
|
||||
builder: (context, child) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvoked: (didPop) async {
|
||||
if (didPop) {
|
||||
return;
|
||||
}
|
||||
await routePush(context,
|
||||
page: const BottomNavigationView(),
|
||||
routeType: RouteType.pushReplace);
|
||||
return false;
|
||||
},
|
||||
child: Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: SizeConfig.height * .1, title: 'Registration'),
|
||||
body: Stack(
|
||||
children: [
|
||||
Column(
|
||||
height: SizeConfig.height * .1,
|
||||
title: 'Registration',
|
||||
leading: BackButtonView(
|
||||
onPress: () {
|
||||
routePush(
|
||||
context,
|
||||
page: const BottomNavigationView(),
|
||||
routeType: RouteType.pushReplace,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -89,8 +102,7 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
||||
horizontal: 16.0, vertical: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children:
|
||||
List.generate(provider.stepAmount, (index) {
|
||||
children: List.generate(provider.stepAmount, (index) {
|
||||
return _stepItem(
|
||||
isCurrentStep:
|
||||
provider.getCurrentStep == index + 1 ||
|
||||
@@ -100,16 +112,13 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: _content(provider.getCurrentStep),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@@ -176,7 +176,9 @@ class SubmitDataIdCard extends StatelessWidget {
|
||||
return SingleChildScrollView(
|
||||
child: Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Column(
|
||||
return Form(
|
||||
key: provider.formKeySubmitIdCard,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const TextCaption(
|
||||
@@ -184,14 +186,35 @@ class SubmitDataIdCard extends StatelessWidget {
|
||||
TextFormView(
|
||||
name: 'NIK',
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormView(
|
||||
name: 'Full Name',
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormView(name: 'Full Name'),
|
||||
DatePickerView(
|
||||
name: 'Birth Date',
|
||||
ctrl: provider.ctrlBirthDate,
|
||||
maxDate: DateTime.now(),
|
||||
isMultipleSelection: false,
|
||||
enabled: true),
|
||||
enabled: true,
|
||||
validatorDate: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
photoDocument(provider),
|
||||
Container(
|
||||
width: SizeConfig.width,
|
||||
@@ -241,14 +264,19 @@ class SubmitDataIdCard extends StatelessWidget {
|
||||
ButtonView(
|
||||
name: 'Next',
|
||||
onPressed: () async {
|
||||
if (provider.formKeySubmitIdCard.currentState!
|
||||
.validate()) {
|
||||
await provider.next(context).then((value) {
|
||||
if (value) {
|
||||
routePush(context, page: const SubmissionParent());
|
||||
routePush(context,
|
||||
page: const SubmissionParent());
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@@ -15,41 +15,70 @@ import 'package:provider/provider.dart';
|
||||
class SubmitEmail extends StatelessWidget {
|
||||
const SubmitEmail({Key? key}) : super(key: key);
|
||||
|
||||
Widget _emailVerify() {
|
||||
return Column(
|
||||
Widget _emailVerify(BuildContext context, SubmissionDataViewModel provider) {
|
||||
var textTheme = Theme.of(context).textTheme;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const TextCaption(title: 'Check your e-mail'),
|
||||
const ImageView(image: PathAssets.imgEmail),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(children: [
|
||||
const TextSpan(
|
||||
TextSpan(
|
||||
text:
|
||||
'We have sent a verification link to your e-mail. \nPlease check your email for ',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
style: textTheme.displayMedium,
|
||||
),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()..onTap = () {},
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
await provider.next(context).then((value) {
|
||||
if (value) {
|
||||
routePush(context, page: const SubmissionParent());
|
||||
}
|
||||
});
|
||||
},
|
||||
text: 'verification',
|
||||
style: const TextStyle(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
const TextSpan(
|
||||
TextSpan(
|
||||
text: ' to \ncontinue registration.',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
style: textTheme.displayMedium,
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
showEmailVerify(BuildContext context, SubmissionDataViewModel provider) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
enableDrag: false,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.zero,
|
||||
),
|
||||
),
|
||||
builder: (context) {
|
||||
var flutterView = View.of(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: MediaQueryData.fromView(flutterView).padding.top,
|
||||
),
|
||||
child: _emailVerify(context, provider),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,16 +89,16 @@ class SubmitEmail extends StatelessWidget {
|
||||
builder: (context, child) {
|
||||
return Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return SingleChildScrollView(
|
||||
return SizedBox(
|
||||
height: SizeConfig.height * .78,
|
||||
child: Form(
|
||||
key: provider.formKeySubmitEmail,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
!provider.isEmailVerify
|
||||
? const TextCaption(title: 'Enter your e-mail')
|
||||
: const TextCaption(title: 'Check your e-mail '),
|
||||
!provider.isEmailVerify
|
||||
? TextFormView(
|
||||
const TextCaption(title: 'Enter your e-mail'),
|
||||
TextFormView(
|
||||
name: 'E-mail Address',
|
||||
hintText: 'Input e-mail address',
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
@@ -82,24 +111,20 @@ class SubmitEmail extends StatelessWidget {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
// onTap: () {
|
||||
// provider.submitEmail();
|
||||
// },
|
||||
)
|
||||
: _emailVerify(),
|
||||
SizedBox(height: SizeConfig.height * .42),
|
||||
),
|
||||
SizedBox(height: SizeConfig.height * .43),
|
||||
ButtonView(
|
||||
name: 'Next',
|
||||
onPressed: () async {
|
||||
await provider.next(context).then((value) {
|
||||
if (value) {
|
||||
routePush(context, page: const SubmissionParent());
|
||||
if (provider.formKeySubmitEmail.currentState!
|
||||
.validate()) {
|
||||
showEmailVerify(context, provider);
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -2,6 +2,7 @@ import 'package:cims_apps/application/component/button/button_view.dart';
|
||||
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||
import 'package:cims_apps/core/route/route.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -17,12 +18,13 @@ class SubmitPersonalData extends StatelessWidget {
|
||||
builder: (context, child) {
|
||||
return Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return SingleChildScrollView(
|
||||
return SizedBox(
|
||||
height: SizeConfig.height * .78,
|
||||
child: Form(
|
||||
key: provider.formKeyPersonalData,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
const TextCaption(title: 'Your personal details'),
|
||||
SelectFormView(
|
||||
@@ -31,6 +33,12 @@ class SubmitPersonalData extends StatelessWidget {
|
||||
ctrl: provider.ctrlOccupation,
|
||||
listItem: provider.listOccupation,
|
||||
onSelect: (value) {},
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SelectFormView(
|
||||
name: 'Income Level (IDR)',
|
||||
@@ -38,6 +46,12 @@ class SubmitPersonalData extends StatelessWidget {
|
||||
ctrl: provider.ctrlIncome,
|
||||
listItem: provider.listIncome,
|
||||
onSelect: (value) {},
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SelectFormView(
|
||||
name: 'Marital Status',
|
||||
@@ -45,6 +59,12 @@ class SubmitPersonalData extends StatelessWidget {
|
||||
ctrl: provider.ctrlMarital,
|
||||
listItem: provider.listMarital,
|
||||
onSelect: (value) {},
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
SelectFormView(
|
||||
name: 'Source of Fund',
|
||||
@@ -52,20 +72,28 @@ class SubmitPersonalData extends StatelessWidget {
|
||||
ctrl: provider.ctrlSourceFund,
|
||||
listItem: provider.listSourceFund,
|
||||
onSelect: (value) {},
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Field must be filled';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: ButtonView(
|
||||
// SizedBox(height: SizeConfig.height * .18),
|
||||
ButtonView(
|
||||
marginVertical: 0,
|
||||
name: 'Next',
|
||||
onPressed: () async {
|
||||
if (provider.formKeyPersonalData.currentState!
|
||||
.validate()) {
|
||||
await provider.next(context).then((value) {
|
||||
if (value) {
|
||||
routePush(context,
|
||||
page: const SubmissionParent());
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@@ -24,15 +24,18 @@ class InitialSignature extends StatelessWidget {
|
||||
builder: (context, child) {
|
||||
return Consumer<SubmissionDataViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Column(
|
||||
return SizedBox(
|
||||
height: SizeConfig.height * .8,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const TextCaption(title: 'Draw your digital sign'),
|
||||
const ImageView(image: PathAssets.frameSignature),
|
||||
const ListTileView(
|
||||
title:
|
||||
'Make sure the sign you draw is match with your ID Card'),
|
||||
SizedBox(height: SizeConfig.height * .07),
|
||||
SizedBox(height: SizeConfig.height * .1),
|
||||
ButtonView(
|
||||
name: 'Next',
|
||||
onPressed: () {
|
||||
@@ -44,6 +47,7 @@ class InitialSignature extends StatelessWidget {
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
||||
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/confirm_bank_account.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
@@ -14,11 +15,16 @@ class SubmissionDataViewModel extends ChangeNotifier {
|
||||
bool _isEmailVerify = false;
|
||||
bool get isEmailVerify => _isEmailVerify;
|
||||
var formKeyPersonalData = GlobalKey<FormState>();
|
||||
var formKeySubmitEmail = GlobalKey<FormState>();
|
||||
var formKeySubmitIdCard = GlobalKey<FormState>();
|
||||
var formKeySubmitDataBank = GlobalKey<FormState>();
|
||||
TextEditingController ctrlOccupation = TextEditingController();
|
||||
TextEditingController ctrlIncome = TextEditingController();
|
||||
TextEditingController ctrlMarital = TextEditingController();
|
||||
TextEditingController ctrlSourceFund = TextEditingController();
|
||||
TextEditingController ctrlBankName = TextEditingController();
|
||||
TextEditingController ctrlNameAccountBank = TextEditingController();
|
||||
TextEditingController ctrlNoAccountBank = TextEditingController();
|
||||
TextEditingController ctrlBankNameSearch = TextEditingController();
|
||||
TextEditingController ctrlBirthDate = TextEditingController();
|
||||
int step = 1;
|
||||
@@ -120,4 +126,21 @@ class SubmissionDataViewModel extends ChangeNotifier {
|
||||
valueBank = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<ModelDataBank> listDataBank = [];
|
||||
|
||||
Future<List<ModelDataBank>?> submitDataBank(
|
||||
{required String bankName, accountNumber, accountName}) async {
|
||||
List<ModelDataBank> listResponse = [
|
||||
ModelDataBank('Bank Name', bankName),
|
||||
ModelDataBank('Account Number', accountNumber),
|
||||
ModelDataBank('Account Owner Name', accountName),
|
||||
ModelDataBank('Name on ID card', accountName),
|
||||
];
|
||||
if (listResponse.first.subtitle != null) {
|
||||
// listDataBank = listResponse;
|
||||
return listResponse;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ 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/plan/view/plan_view.dart';
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart';
|
||||
import 'package:cims_apps/features/profile/view/profile_view.dart';
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/profile/view/profile_view.dart';
|
||||
import 'package:cims_apps/features/transaction/view/transaction_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
@@ -50,7 +50,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
];
|
||||
|
||||
StepVerification listStepVerification =
|
||||
StepVerification(0, ['Registration', 'Verification', 'Complete']);
|
||||
StepVerification(1, ['Registration', '', 'Verification', '', 'Complete']);
|
||||
|
||||
List<Article> listArticle = [
|
||||
Article(
|
||||
@@ -69,12 +69,21 @@ class _HomeViewState extends State<HomeView> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xffF8FAFC),
|
||||
body: SizedBox(
|
||||
width: SizeConfig.width,
|
||||
height: SizeConfig.height,
|
||||
child: Stack(
|
||||
backgroundColor: ColorPalette.slate50,
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
onStretchTrigger: () async {
|
||||
},
|
||||
expandedHeight: 325,
|
||||
collapsedHeight: 325,
|
||||
leading: const SizedBox(),
|
||||
surfaceTintColor: ColorPalette.slate50,
|
||||
backgroundColor: ColorPalette.slate50,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: Stack(
|
||||
children: [
|
||||
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||
Column(
|
||||
@@ -118,11 +127,18 @@ class _HomeViewState extends State<HomeView> {
|
||||
),
|
||||
cardInvestType(),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
height: 24,
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(0),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
floating: true,
|
||||
snap: true,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
children: [
|
||||
cardVerification(),
|
||||
const SizedBox(
|
||||
@@ -135,12 +151,9 @@ class _HomeViewState extends State<HomeView> {
|
||||
articles(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -279,6 +292,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
child: Column(
|
||||
children: [
|
||||
stepVerification(),
|
||||
if(listStepVerification.currentStep < 3)
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
@@ -291,6 +305,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
Icon(
|
||||
Icons.verified,
|
||||
size: 18,
|
||||
color: ColorPalette.slate300,
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
@@ -324,6 +339,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
Icon(
|
||||
Icons.verified,
|
||||
size: 18,
|
||||
color: ColorPalette.slate300,
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
@@ -388,11 +404,11 @@ class _HomeViewState extends State<HomeView> {
|
||||
borderRadius: BorderRadius.circular(12)),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
"Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia",
|
||||
style: TextStyle(color: ColorPalette.slate500),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
ButtonView(
|
||||
@@ -400,9 +416,9 @@ class _HomeViewState extends State<HomeView> {
|
||||
width: SizeConfig.width,
|
||||
marginVertical: 0,
|
||||
heightWrapContent: true,
|
||||
contentPadding: EdgeInsets.all(12),
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
onPressed: () {
|
||||
routePush(context, page: InitialRegistrationStep());
|
||||
routePush(context, page: const InitialRegistrationStep());
|
||||
},
|
||||
)
|
||||
],
|
||||
@@ -417,57 +433,61 @@ class _HomeViewState extends State<HomeView> {
|
||||
Widget stepVerification() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: listStepVerification.nameStep.asMap().entries.map((e) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (e.key != 0)
|
||||
SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: Divider(
|
||||
color: listStepVerification.currentStep >= e.key
|
||||
? const Color(0xff2563EB)
|
||||
: const Color(0xffCBD5E1),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: List.generate(
|
||||
listStepVerification.nameStep.length,
|
||||
(index) {
|
||||
print(index % 2);
|
||||
if (index % 2 == 0) {
|
||||
final currentStep = index ~/ 2;
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: listStepVerification.currentStep <= e.key
|
||||
color: listStepVerification.currentStep <= currentStep
|
||||
? Colors.white
|
||||
: const Color(0xff2563EB),
|
||||
border: Border.all(
|
||||
color: listStepVerification.currentStep < e.key
|
||||
color: listStepVerification.currentStep < currentStep
|
||||
? const Color(0xffCBD5E1)
|
||||
: const Color(0xff2563EB),
|
||||
width: 2)),
|
||||
child: listStepVerification.currentStep <= e.key
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: listStepVerification.currentStep <= currentStep
|
||||
? const SizedBox()
|
||||
: const Icon(
|
||||
Icons.done_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
e.value,
|
||||
listStepVerification.nameStep[index],
|
||||
style: TextStyle(
|
||||
color: listStepVerification.currentStep == e.key
|
||||
color: listStepVerification.currentStep == currentStep
|
||||
? const Color(0xff2563EB)
|
||||
: Colors.black),
|
||||
)
|
||||
],
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
} else {
|
||||
return SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: Divider(
|
||||
color: listStepVerification.currentStep > index ~/ 2
|
||||
? const Color(0xff2563EB)
|
||||
: const Color(0xffCBD5E1),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -591,7 +611,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
color: ColorPalette.green100),
|
||||
child: Text(
|
||||
article.type,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorPalette.green500),
|
||||
),
|
||||
|
@@ -1,12 +1,8 @@
|
||||
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/subscribe/goal_investing_view.dart';
|
||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||
import 'package:cims_apps/application/component/risk_profile.dart';
|
||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||
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/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';
|
||||
@@ -46,33 +42,32 @@ class _PlanViewState extends State<PlanView> {
|
||||
appBar: CustomAppBar(
|
||||
height: SizeConfig.height * 0.08,
|
||||
title: 'Investment Plan',
|
||||
leading: SizedBox(),
|
||||
leading: const SizedBox(),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(24),
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RiskProfile(
|
||||
const RiskProfile(
|
||||
totalScore: 26,
|
||||
rowSuitableProduct: true
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
Text('Your Goal in Investing',
|
||||
const Text('Your Goal in Investing',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorPalette.slate800,
|
||||
fontSize: 18
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
GoalInvestingView(
|
||||
onListSelected: (p0) {
|
||||
print(p0);
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
@@ -103,7 +98,7 @@ class _PlanViewState extends State<PlanView> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("It's time to invest",
|
||||
const Text("It's time to invest",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600
|
||||
@@ -113,17 +108,20 @@ class _PlanViewState extends State<PlanView> {
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Icon(Icons.close_rounded)
|
||||
child: const Icon(Icons.close_rounded)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(color: ColorPalette.slate200, height: 1),
|
||||
const Divider(color: ColorPalette.slate200, height: 1),
|
||||
InputInvestmentView(
|
||||
selectedPlan: text,
|
||||
currentPlan: text,
|
||||
changePlan: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
nextMove: (value) {
|
||||
Navigator.pop(context);
|
||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
|
||||
},
|
||||
),
|
||||
|
@@ -4,6 +4,7 @@ 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/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';
|
||||
@@ -18,29 +19,33 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
List<PortfolioProduct> listProduct = [
|
||||
PortfolioProduct(
|
||||
name: 'Gemilang Dana Kas Maxima',
|
||||
type: '',
|
||||
type: 'Money Market',
|
||||
yield: 8.17,
|
||||
priceUnit: 2600.79,
|
||||
funds: 6300000),
|
||||
funds: 6300000,
|
||||
totalUnit: 14520
|
||||
),
|
||||
PortfolioProduct(
|
||||
name: 'Gemilang Dana Likuid',
|
||||
type: '',
|
||||
type: 'Sharia',
|
||||
yield: 6.42,
|
||||
priceUnit: 1600.79,
|
||||
funds: 2340000),
|
||||
funds: 2340000,
|
||||
totalUnit: 232,
|
||||
),
|
||||
PortfolioProduct(
|
||||
name: 'Gemilang Income Fund',
|
||||
type: '',
|
||||
type: 'Bonds',
|
||||
yield: 8.17,
|
||||
priceUnit: 2600.79,
|
||||
funds: 6300000)
|
||||
funds: 6300000,
|
||||
totalUnit: 2450,
|
||||
)
|
||||
];
|
||||
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (context) => RedeemProductViewModel())
|
||||
],
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => RedeemProductViewModel(),
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SizedBox(
|
||||
@@ -100,19 +105,20 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 24,),
|
||||
Expanded(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: ListView(
|
||||
child: Consumer<RedeemProductViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
children: [
|
||||
cardPortfolio(context)
|
||||
],
|
||||
),
|
||||
children: listProduct.asMap().entries.map((e) {
|
||||
return cardPortfolio(context, e.value);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
@@ -125,7 +131,7 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget cardPortfolio(context) {
|
||||
Widget cardPortfolio(context, PortfolioProduct product) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
@@ -155,19 +161,19 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||
TextTitle(title: product.name ?? '', 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)
|
||||
color: ColorPalette.investTypeBgColor[product.type!]?.withOpacity(0.5) ?? Colors.white,
|
||||
border: Border.all(width: 2, color: ColorPalette.investTypeColor[product.type!]?.withOpacity(0.4) ?? Colors.white)
|
||||
),
|
||||
child: Text(
|
||||
'Money Market' ?? '',
|
||||
product.type ?? '',
|
||||
style: TextStyle(
|
||||
color: ColorPalette.investTypeColor['Money Market'],
|
||||
color: ColorPalette.investTypeColor[product.type!],
|
||||
fontWeight: FontWeight.w600
|
||||
),
|
||||
),
|
||||
@@ -187,8 +193,8 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
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'),
|
||||
rowDescription('Purchase Price', NumberFormatter.numberCurrency(product.priceUnit, 'Rp ', 'id_ID')),
|
||||
rowDescription('Number of Units', '${product.totalUnit ?? 0}'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16,),
|
||||
@@ -206,6 +212,7 @@ class PortfolioDetailView extends StatelessWidget {
|
||||
borderColor: ColorPalette.red600,
|
||||
textColor: ColorPalette.red600,
|
||||
onPressed: () {
|
||||
Provider.of<RedeemProductViewModel>(context, listen: false).setProduct(product);
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
|
@@ -388,7 +388,7 @@ class _PortofolioViewState extends State<PortofolioView> {
|
||||
Widget cardPortfolio() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
routePush(context, page: const PortfolioDetailView());
|
||||
// routePush(context, page: const PortfolioDetailView());
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
|
@@ -4,6 +4,7 @@ import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||
@@ -82,84 +83,19 @@ class _ChangeAmountState extends State<ChangeAmount> {
|
||||
),
|
||||
),
|
||||
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Column(
|
||||
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
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: cardProduct()
|
||||
),
|
||||
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('.', '');
|
||||
InputInvestmentView(
|
||||
minimumPrice: (provider.getCurrentProduct.priceUnit! * 1).toInt(),
|
||||
maximumPrice: (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(),
|
||||
currentPrice: provider.getAmount!.toInt(),
|
||||
nextMove: (value) {
|
||||
String formatValueInput = value.replaceAll('Rp ', '').replaceAll('.', '');
|
||||
provider.setAmount(double.parse(formatValueInput));
|
||||
Navigator.pop(context);
|
||||
showModalBottomSheet(
|
||||
@@ -173,7 +109,7 @@ class _ChangeAmountState extends State<ChangeAmount> {
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
SizedBox(height: 16,)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@@ -42,8 +42,7 @@ class _RedeemProductState extends State<RedeemProduct> {
|
||||
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);
|
||||
amountController.text = NumberFormatter.numberCurrency(provider.getAmount!.toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -76,8 +75,8 @@ class _RedeemProductState extends State<RedeemProduct> {
|
||||
const SizedBox(height: 16),
|
||||
segmentAmount(
|
||||
context,
|
||||
provider.getAmount ?? provider.getCurrentProduct.priceUnit! * (provider.getCurrentProduct.totalUnit! / 2.0),
|
||||
provider.getUnit ?? provider.getCurrentProduct.totalUnit! / 2.0,
|
||||
provider.getAmount!,
|
||||
provider.getUnit!,
|
||||
(value) {
|
||||
provider.setUnit(value);
|
||||
},
|
||||
|
@@ -61,6 +61,8 @@ class RedeemProductViewModel extends ChangeNotifier {
|
||||
|
||||
void setProduct(PortfolioProduct product) {
|
||||
currentProduct = product;
|
||||
amount = product.priceUnit! * (product.totalUnit! / 2.0);
|
||||
unit = (product.totalUnit! / 2.0);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart';
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:group_button/group_button.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -79,6 +80,8 @@ class _ProductViewState extends State<ProductView> {
|
||||
});
|
||||
}
|
||||
|
||||
double currentScroll = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
machineController.text = NumberFormatter.numberCurrency(100000, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||
@@ -104,21 +107,45 @@ class _ProductViewState extends State<ProductView> {
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => ProductViewModel(),
|
||||
child: Scaffold(
|
||||
body: SizedBox(
|
||||
child: Stack(
|
||||
children: [
|
||||
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
body: NotificationListener<ScrollNotification>(
|
||||
onNotification: (notification) {
|
||||
setState(() {
|
||||
currentScroll = notification.metrics.pixels;
|
||||
});
|
||||
return false;
|
||||
},
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
toolbarHeight: 70,
|
||||
expandedHeight: 170,
|
||||
leadingWidth: 0,
|
||||
floating: false,
|
||||
automaticallyImplyLeading: false,
|
||||
title: AnimatedCrossFade(
|
||||
firstChild: Text(
|
||||
widget.selectedProduct.name ?? '',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BackButtonView(),
|
||||
),
|
||||
secondChild: Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: BackButtonView(),
|
||||
),
|
||||
crossFadeState: currentScroll >= 85 ? CrossFadeState.showFirst : CrossFadeState.showSecond,
|
||||
duration: Duration(milliseconds: 200)
|
||||
),
|
||||
centerTitle: false,
|
||||
snap: false,
|
||||
pinned: true,
|
||||
backgroundColor: Color(0xFF1745C8).withOpacity(currentScroll >= 95 ? 1 : currentScroll / 95),
|
||||
surfaceTintColor: ColorPalette.primary,
|
||||
actions: [
|
||||
Wrap(
|
||||
spacing: 12,
|
||||
children: [
|
||||
@@ -126,25 +153,43 @@ class _ProductViewState extends State<ProductView> {
|
||||
Icon(Icons.file_download_outlined, color: ColorPalette.blue200, size: 32),
|
||||
Icon(Icons.star_outline_rounded, color: ColorPalette.blue200, size: 32)
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(width: 24,)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
flexibleSpace: Opacity(
|
||||
opacity: currentScroll > 0 ? ((95 - currentScroll) / 95) > 0.01 ? ((95 - currentScroll) / 95) : 0 : 1,
|
||||
child: Stack(
|
||||
children: [
|
||||
ImageView(image: PathAssets.imgDashboardAccount, width: SizeConfig.width, height: 200),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
headContainer(),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Expanded(
|
||||
child: contentContainer()
|
||||
Container(
|
||||
height: 12,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12)
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: contentContainer(),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: !widget.seeMore ?
|
||||
Container(
|
||||
height: SizeConfig.height * .1,
|
||||
@@ -220,8 +265,11 @@ class _ProductViewState extends State<ProductView> {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: ListView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
ProductChartView(
|
||||
tabType: listTab[selectedTab],
|
||||
lastTime: selectedTime.completeName,
|
||||
|
@@ -55,11 +55,21 @@ class SelectGoalInvesting extends StatelessWidget {
|
||||
create: (context) => ProductViewModel(),
|
||||
child: Consumer<ProductViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return InputInvestmentView(
|
||||
selectedPlan: p0,
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: InputInvestmentView(
|
||||
currentPlan: p0,
|
||||
changePlan: () {
|
||||
Navigator.pop(context);
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => SelectGoalInvesting(),
|
||||
);
|
||||
},
|
||||
nextMove: (value) {
|
||||
Navigator.pop(context);
|
||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
@@ -81,6 +91,7 @@ class SelectGoalInvesting extends StatelessWidget {
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
|
@@ -0,0 +1,165 @@
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/profile/view_model/profile_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class RouteNavigation {
|
||||
String icon;
|
||||
String title;
|
||||
Widget destination;
|
||||
|
||||
RouteNavigation(this.icon, this.title, this.destination);
|
||||
}
|
||||
|
||||
class ProfileView extends StatelessWidget {
|
||||
const ProfileView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<RouteNavigation> listGeneral = [
|
||||
RouteNavigation(PathAssets.iconProfile, 'Personal Data', Container()),
|
||||
RouteNavigation(PathAssets.iconPadlock, 'Change Password', Container()),
|
||||
RouteNavigation(PathAssets.iconCard, 'Add Card', Container()),
|
||||
RouteNavigation(PathAssets.iconSetting, 'Settings', Container())
|
||||
];
|
||||
|
||||
List<RouteNavigation> listPreferences = [
|
||||
RouteNavigation(PathAssets.iconFaqs, 'FAQs', Container()),
|
||||
RouteNavigation(PathAssets.iconLogout, 'Log Out', Container())
|
||||
];
|
||||
|
||||
return Provider(
|
||||
create: (context) => ProfileViewModel(),
|
||||
child: Scaffold(
|
||||
body: SizedBox(
|
||||
width: SizeConfig.width,
|
||||
height: SizeConfig.height,
|
||||
child: Stack(
|
||||
children: [
|
||||
const Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: ImageView(image: PathAssets.imgDashboardProfile)
|
||||
),
|
||||
Consumer<ProfileViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(0),
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
const Center(
|
||||
child: TextTitle(title: 'Profile', color: Colors.white, fontSize: 20,)
|
||||
),
|
||||
SizedBox(
|
||||
height: SizeConfig.height * 0.05,
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.white,
|
||||
border: Border.all(color: ColorPalette.slate200, width: 1.5)
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: ImageView(image: PathAssets.iconCat, width: SizeConfig.width * 0.14,),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Center(
|
||||
child: TextTitle(title: provider.getUser.name ?? '', color: Colors.white, fontSize: 24,)),
|
||||
Text('Investor ${provider.getUser.risk}',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: ColorPalette.textRiskColor[provider.getUser.risk]
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
boxNavigation('General', listGeneral),
|
||||
const SizedBox(height: 24),
|
||||
boxNavigation('Preferences', listPreferences)
|
||||
],
|
||||
);
|
||||
}
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget boxNavigation(String title, List<RouteNavigation> list) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorPalette.slate400
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
runSpacing: 16,
|
||||
children: list.map((e) {
|
||||
return rowNavigation(
|
||||
e.icon,
|
||||
e.title,
|
||||
e.destination
|
||||
);
|
||||
}).toList(),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget rowNavigation(String icon, String text, Widget destination) {
|
||||
bool isLogout = text == 'Log Out';
|
||||
Color textColor = isLogout ? ColorPalette.red600 : ColorPalette.slate800;
|
||||
Color bgLeadingColor = isLogout ? ColorPalette.red50 : ColorPalette.blue50;
|
||||
Color iconColor = isLogout ? ColorPalette.red600 : ColorPalette.blue600;
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: bgLeadingColor
|
||||
),
|
||||
child: Image.asset(icon, width: SizeConfig.width * 0.05, color: iconColor)
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(text,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: textColor
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.chevron_right_outlined, size: 28, color: ColorPalette.slate400)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
class User {
|
||||
String? name, risk;
|
||||
|
||||
User({this.name, this.risk});
|
||||
}
|
||||
|
||||
class ProfileViewModel {
|
||||
static final User _user = User(name: 'Muhammad Rosyidin', risk: 'Conservative');
|
||||
|
||||
User get getUser => _user;
|
||||
}
|
@@ -44,7 +44,7 @@ class DashboardPublicView extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0,
|
||||
bottom: 24.0,
|
||||
left: 24.0,
|
||||
right: 24.0,
|
||||
),
|
||||
@@ -59,6 +59,7 @@ class DashboardPublicView extends StatelessWidget {
|
||||
image: PathAssets.icon1,
|
||||
width: SizeConfig.width * .35,
|
||||
),
|
||||
SizedBox(height: SizeConfig.height * .02),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
heightFactor: 1,
|
||||
@@ -105,7 +106,7 @@ class DashboardPublicView extends StatelessWidget {
|
||||
provider.loginGoogle(context);
|
||||
},
|
||||
),
|
||||
SizedBox(height: SizeConfig.height * .1),
|
||||
SizedBox(height: SizeConfig.height * .07),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
@@ -1,14 +0,0 @@
|
||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ProfileView extends StatelessWidget {
|
||||
const ProfileView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(height: SizeConfig.height * .08, title: 'Profile'),
|
||||
);
|
||||
}
|
||||
}
|
35
lib/features/transaction/view/cancel_view.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CancelView extends StatelessWidget {
|
||||
const CancelView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Consumer<TransactionViewModel>(
|
||||
builder: (context, provider, child) => Column(
|
||||
children: [
|
||||
if (provider.listOnProcessTransaction.isEmpty)
|
||||
EmptyCardTransaction(
|
||||
onPressedButton: () {},
|
||||
),
|
||||
...provider.listOnProcessTransaction.map((e) {
|
||||
return CardTransactionView(
|
||||
step: 'cancel',
|
||||
type: 'type',
|
||||
amount: 'amount',
|
||||
iconPath: 'iconPath',
|
||||
subs: 'subs',
|
||||
onTap: () {},
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
37
lib/features/transaction/view/done_view.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class DoneView extends StatelessWidget {
|
||||
const DoneView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Consumer<TransactionViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return Column(
|
||||
children: [
|
||||
if (provider.listOnProcessTransaction.isEmpty)
|
||||
EmptyCardTransaction(
|
||||
onPressedButton: () {},
|
||||
),
|
||||
...provider.listOnProcessTransaction.map((e) {
|
||||
return CardTransactionView(
|
||||
step: 'done',
|
||||
type: 'type',
|
||||
amount: 'amount',
|
||||
iconPath: 'iconPath',
|
||||
subs: 'subs',
|
||||
onTap: () {},
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
34
lib/features/transaction/view/onprocess_view.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class OnProcessView extends StatelessWidget {
|
||||
const OnProcessView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child:
|
||||
Consumer<TransactionViewModel>(builder: (context, provider, child) {
|
||||
return Column(children: [
|
||||
if (provider.listOnProcessTransaction.isEmpty)
|
||||
EmptyCardTransaction(
|
||||
onPressedButton: () {},
|
||||
),
|
||||
...provider.listOnProcessTransaction.map((e) {
|
||||
return CardTransactionView(
|
||||
step: 'on process',
|
||||
type: 'type',
|
||||
amount: 'amount',
|
||||
iconPath: 'iconPath',
|
||||
subs: 'subs',
|
||||
onTap: () {},
|
||||
);
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,14 +1,124 @@
|
||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.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/theme/color_palette.dart';
|
||||
import 'package:cims_apps/core/utils/size_config.dart';
|
||||
import 'package:cims_apps/features/transaction/view/cancel_view.dart';
|
||||
import 'package:cims_apps/features/transaction/view/done_view.dart';
|
||||
import 'package:cims_apps/features/transaction/view/onprocess_view.dart';
|
||||
import 'package:cims_apps/features/transaction/view/waiting_view.dart';
|
||||
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_toggle_tab/flutter_toggle_tab.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class TransactionView extends StatelessWidget {
|
||||
const TransactionView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Tab> textTabs = const [
|
||||
Tab(text: 'Waiting'),
|
||||
Tab(text: 'On process'),
|
||||
Tab(text: 'Done'),
|
||||
Tab(text: 'Cancel'),
|
||||
];
|
||||
List<Widget> listTabBarView = const [
|
||||
WaitingView(),
|
||||
OnProcessView(),
|
||||
DoneView(),
|
||||
CancelView(),
|
||||
];
|
||||
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => TransactionViewModel(),
|
||||
builder: (context, child) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(height: SizeConfig.height * 0.08, title: 'Transaction'),
|
||||
backgroundColor: ColorPalette.primary,
|
||||
body: SizedBox(
|
||||
child: Stack(
|
||||
children: [
|
||||
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: SizeConfig.height * .05,
|
||||
),
|
||||
const Center(
|
||||
child: Text(
|
||||
'Transaction',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: SizeConfig.height * .04,
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: FlutterToggleTab(
|
||||
height: SizeConfig.height * .065,
|
||||
width: SizeConfig.width * .2,
|
||||
marginSelected: const EdgeInsets.all(8.0),
|
||||
isScroll: false,
|
||||
selectedTextStyle: const TextStyle(
|
||||
color: ColorPalette.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
unSelectedTextStyle: const TextStyle(
|
||||
color: ColorPalette.blackFont,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
unSelectedBackgroundColors: const [
|
||||
ColorPalette.blue50
|
||||
],
|
||||
selectedBackgroundColors: const [ColorPalette.white],
|
||||
labels: const ['Subscribe', 'Reedem'],
|
||||
selectedLabelIndex: (p0) {},
|
||||
selectedIndex: 0,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultTabController(
|
||||
length: textTabs.length,
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.only(top: 32.0),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(top: 24),
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
topRight: Radius.circular(24)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
TabBar(
|
||||
tabs: textTabs,
|
||||
indicatorColor: Colors.blueAccent,
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 4.0,
|
||||
),
|
||||
child: TabBarView(children: listTabBarView),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
42
lib/features/transaction/view/waiting_view.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class WaitingView extends StatelessWidget {
|
||||
const WaitingView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child:
|
||||
Consumer<TransactionViewModel>(builder: (context, provider, child) {
|
||||
return Column(
|
||||
children: [
|
||||
provider.listWaitingTransaction.isNotEmpty
|
||||
? CardTransactionView(
|
||||
onTap: () {},
|
||||
iconPath: PathAssets.iconEducation,
|
||||
type: 'Education',
|
||||
amount: NumberFormatter.numberCurrency(
|
||||
6000000,
|
||||
'Rp ',
|
||||
'id_ID',
|
||||
decimalDigits: 0,
|
||||
),
|
||||
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||
subs: '3 Subscription',
|
||||
step: 'waiting')
|
||||
: EmptyCardTransaction(
|
||||
onPressedButton: () {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TransactionViewModel extends ChangeNotifier {
|
||||
List listWaitingTransaction = [1];
|
||||
List listOnProcessTransaction = [];
|
||||
List listDoneTransaction = [];
|
||||
List listCancelTransaction = [];
|
||||
}
|
@@ -76,10 +76,8 @@ class MyApp extends StatelessWidget {
|
||||
secondary: const Color(0xFFFECDA6),
|
||||
onBackground: const Color(0xFFA9A9A9),
|
||||
),
|
||||
bottomSheetTheme: BottomSheetThemeData(
|
||||
backgroundColor: Colors.white,
|
||||
surfaceTintColor: Colors.white
|
||||
)
|
||||
bottomSheetTheme: const BottomSheetThemeData(
|
||||
backgroundColor: Colors.white, surfaceTintColor: Colors.white)
|
||||
// useMaterial3: true,
|
||||
),
|
||||
initialRoute: initialRoute,
|
||||
|
@@ -259,6 +259,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_toggle_tab:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_toggle_tab
|
||||
sha256: "90ad0d050f656df677998825f985637d010117a1793828cd7e6dadada4ecd2c5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@@ -53,6 +53,7 @@ dependencies:
|
||||
shared_preferences: ^2.2.2
|
||||
calendar_date_picker2: ^0.5.3
|
||||
google_sign_in: ^6.2.1
|
||||
flutter_toggle_tab: ^1.4.1
|
||||
|
||||
|
||||
|
||||
|