Compare commits
27 Commits
6a43a3dcaf
...
dev
Author | SHA1 | Date | |
---|---|---|---|
848891e1f4 | |||
4f2380fcdf | |||
c23075304a | |||
17c7559158 | |||
711e5f3f52 | |||
a99365fb0a | |||
41f0bb7a68 | |||
c97130239d | |||
1b867227c7 | |||
4b07219928 | |||
9cdda42b8b | |||
6f5d3ccca8 | |||
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: 2.3 KiB |
BIN
assets/icons/icon-chat.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/icons/icon-education.png
Normal file
After Width: | Height: | Size: 3.8 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: 2.7 KiB |
BIN
assets/icons/icon-profile.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/icons/icon-setting.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/icons/icon-shop.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/images/bg-profile.png
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/images/img-cat-outlined.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/img-empty-transaction.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
assets/images/img-expand-purchase.png
Normal file
After Width: | Height: | Size: 32 KiB |
@@ -49,12 +49,28 @@ class PathAssets {
|
|||||||
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
||||||
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
||||||
static const String iconCar = 'assets/icons/icon-car.png';
|
static const String iconCar = 'assets/icons/icon-car.png';
|
||||||
static const String iconNavigationHome = 'assets/icons/icon-navigation-home.png';
|
static const String iconNavigationHome =
|
||||||
static const String iconNavigationPlan = 'assets/icons/icon-navigation-plan.png';
|
'assets/icons/icon-navigation-home.png';
|
||||||
static const String iconNavigationTransaction = 'assets/icons/icon-navigation-transaction.png';
|
static const String iconNavigationPlan =
|
||||||
static const String iconNavigationPortfolio = 'assets/icons/icon-navigation-portfolio.png';
|
'assets/icons/icon-navigation-plan.png';
|
||||||
static const String iconNavigationProfile = 'assets/icons/icon-navigation-profile.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 iconRemove = 'assets/icons/icon-remove.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 iconCard = 'assets/icons/icon-card.png';
|
||||||
|
static const String iconChat = 'assets/icons/icon-chat.png';
|
||||||
|
static const String iconLogout = 'assets/icons/icon-logout.png';
|
||||||
|
static const String iconProfile = 'assets/icons/icon-profile.png';
|
||||||
|
static const String iconSetting = 'assets/icons/icon-setting.png';
|
||||||
|
static const String iconGadgetOutline =
|
||||||
|
'assets/icons/icon-gadget-outline.png';
|
||||||
|
|
||||||
/// IMAGE
|
/// IMAGE
|
||||||
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
||||||
@@ -83,15 +99,22 @@ class PathAssets {
|
|||||||
static const String imgMoneyIncome = 'assets/images/img-money-income.png';
|
static const String imgMoneyIncome = 'assets/images/img-money-income.png';
|
||||||
static const String imgGrowing = 'assets/images/img-growing.png';
|
static const String imgGrowing = 'assets/images/img-growing.png';
|
||||||
static const String imgCat = 'assets/images/img-cat.png';
|
static const String imgCat = 'assets/images/img-cat.png';
|
||||||
|
static const String imgCatOutlined = 'assets/images/img-cat-outlined.png';
|
||||||
static const String imgDeer = 'assets/images/img-deer.png';
|
static const String imgDeer = 'assets/images/img-deer.png';
|
||||||
static const String imgLion = 'assets/images/img-lion.png';
|
static const String imgLion = 'assets/images/img-lion.png';
|
||||||
static const String imgGuideBank = 'assets/images/img-guide-bank.png';
|
static const String imgGuideBank = 'assets/images/img-guide-bank.png';
|
||||||
static const String imgGuide1 = 'assets/images/img-guide1.png';
|
static const String imgGuide1 = 'assets/images/img-guide1.png';
|
||||||
static const String imgGuide2 = 'assets/images/img-guide2.png';
|
static const String imgGuide2 = 'assets/images/img-guide2.png';
|
||||||
static const String imgOpenShopping = 'assets/images/img-open-shopping.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 frameSignature = 'assets/images/frame-signature.png';
|
||||||
static const String imgFinish = 'assets/images/img-finish.png';
|
static const String imgFinish = 'assets/images/img-finish.png';
|
||||||
|
static const String imgExpandPurchase =
|
||||||
|
'assets/images/img-expand-purchase.png';
|
||||||
|
static const String imgEmptyTransaction =
|
||||||
|
'assets/images/img-empty-transaction.png';
|
||||||
|
static const String bgProfile = 'assets/images/bg-profile.png';
|
||||||
|
|
||||||
static const Map<String, String> goalInvestIcon = {
|
static const Map<String, String> goalInvestIcon = {
|
||||||
'Education': iconToga,
|
'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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -8,22 +8,26 @@ class ListTileView extends StatelessWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
final VoidCallback? onPressed;
|
final VoidCallback? onPressed;
|
||||||
final Widget? prefixIcon, suffixIcon;
|
final Widget? prefixIcon, suffixIcon;
|
||||||
final Color? colorTitle;
|
final EdgeInsetsGeometry? padding, margin;
|
||||||
|
final TextStyle? textStyle;
|
||||||
const ListTileView(
|
const ListTileView(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.prefixIcon,
|
this.prefixIcon,
|
||||||
this.suffixIcon,
|
this.suffixIcon,
|
||||||
this.colorTitle})
|
this.padding,
|
||||||
|
this.textStyle,
|
||||||
|
this.margin})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
|
padding: padding ??
|
||||||
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
|
||||||
|
margin: margin ?? const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: ColorPalette.blue50,
|
color: ColorPalette.blue50,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@@ -47,22 +51,23 @@ class ListTileView extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyle(
|
style: textStyle ??
|
||||||
fontWeight: FontWeight.w600,
|
const TextStyle(
|
||||||
color: colorTitle ?? ColorPalette.slate500,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
suffixIcon != null
|
suffixIcon ??
|
||||||
? IconButton(
|
IconButton(
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
: const SizedBox(),
|
// : const SizedBox(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -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:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -44,28 +45,11 @@ class RadioAgreement extends StatelessWidget {
|
|||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: ExpandableWidget(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
content: desc,
|
||||||
children: [
|
maxLinesToShow: 3,
|
||||||
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),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
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/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
||||||
@@ -73,20 +74,20 @@ class RiskProfile extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
riskProfile.type,
|
riskProfile.type,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
color: ColorPalette.white
|
color: ColorPalette.white
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16,),
|
const SizedBox(height: 16,),
|
||||||
Text('Total Score :',
|
const Text('Total Score :',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -94,7 +95,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('$totalScore',
|
Text('$totalScore',
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
color: ColorPalette.white
|
color: ColorPalette.white
|
||||||
@@ -107,20 +108,20 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
Text(
|
ExpandableWidget(
|
||||||
riskProfile.desc,
|
content: riskProfile.desc,
|
||||||
style: TextStyle(
|
hideTextMore: true,
|
||||||
color: ColorPalette.slate500,
|
hideIconMore: false,
|
||||||
fontSize: 16
|
maxLinesToShow: 4,
|
||||||
)
|
alignmentMore: Alignment.center,
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
Text(
|
const Text(
|
||||||
'Suitable Product',
|
'Suitable Product',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
@@ -128,7 +129,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
fontSize: 18
|
fontSize: 18
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
rowSuitableProduct ?
|
rowSuitableProduct ?
|
||||||
@@ -137,7 +138,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0),
|
margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0),
|
||||||
padding: EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
borderRadius: BorderRadius.circular(6)
|
borderRadius: BorderRadius.circular(6)
|
||||||
@@ -146,18 +147,18 @@ class RiskProfile extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: riskProfile.color.withOpacity(0.1)
|
color: riskProfile.color.withOpacity(0.1)
|
||||||
),
|
),
|
||||||
child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Text(e.value['desc'],
|
Text(e.value['desc'],
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
@@ -173,7 +174,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: riskProfile.suitableProduct.map((e) {
|
children: riskProfile.suitableProduct.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
@@ -181,7 +182,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
@@ -189,12 +190,12 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(e['desc'],
|
child: Text(e['desc'],
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorPalette.slate800
|
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/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -6,9 +8,13 @@ import 'package:cims_apps/core/utils/size_config.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InputInvestmentView extends StatefulWidget {
|
class InputInvestmentView extends StatefulWidget {
|
||||||
final String selectedPlan;
|
final String? currentPlan;
|
||||||
|
final void Function()? changePlan;
|
||||||
|
final int? currentPrice;
|
||||||
|
final int? minimumPrice;
|
||||||
|
final int? maximumPrice;
|
||||||
final void Function(String value) nextMove;
|
final void Function(String value) nextMove;
|
||||||
const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove});
|
const InputInvestmentView({super.key, required this.nextMove, this.currentPlan, this.minimumPrice, this.maximumPrice, this.currentPrice, this.changePlan});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<InputInvestmentView> createState() => _InputInvestmentViewState();
|
State<InputInvestmentView> createState() => _InputInvestmentViewState();
|
||||||
@@ -17,10 +23,35 @@ class InputInvestmentView extends StatefulWidget {
|
|||||||
class _InputInvestmentViewState extends State<InputInvestmentView> {
|
class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||||
TextEditingController inputController = TextEditingController();
|
TextEditingController inputController = TextEditingController();
|
||||||
|
|
||||||
|
void validationInputValue(String currentValue) {
|
||||||
|
currentValue = currentValue.replaceAll('Rp ', '').replaceAll('.', '');
|
||||||
|
if(currentValue.isEmpty){
|
||||||
|
currentValue = '0';
|
||||||
|
}
|
||||||
|
double parseValue = double.parse(currentValue);
|
||||||
|
if(widget.minimumPrice != null){
|
||||||
|
if(parseValue <= widget.minimumPrice!){
|
||||||
|
parseValue = widget.minimumPrice!.toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widget.maximumPrice != null){
|
||||||
|
if(parseValue >= widget.maximumPrice!){
|
||||||
|
parseValue = widget.maximumPrice!.toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
inputController.text = 'Rp 0';
|
if(widget.currentPrice != null){
|
||||||
|
inputController.text = NumberFormatter.numberCurrency(widget.currentPrice, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}else{
|
||||||
|
inputController.text = 'Rp 0';
|
||||||
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,55 +72,53 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 16),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
if(widget.currentPlan != null)
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
Text(widget.selectedPlan,
|
children: [
|
||||||
style: TextStyle(
|
Text(widget.currentPlan ?? '',
|
||||||
fontSize: 20,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
InkWell(
|
||||||
Row(
|
borderRadius: BorderRadius.circular(16),
|
||||||
children: [
|
onTap: widget.changePlan,
|
||||||
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
child: const Row(
|
||||||
SizedBox(width: 4),
|
children: [
|
||||||
Text('Change',
|
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
||||||
style: TextStyle(
|
SizedBox(width: 4),
|
||||||
fontSize: 16,
|
Text('Change',
|
||||||
fontWeight: FontWeight.w600,
|
style: TextStyle(
|
||||||
color: ColorPalette.primary
|
fontSize: 16,
|
||||||
),
|
fontWeight: FontWeight.w600,
|
||||||
)
|
color: ColorPalette.primary
|
||||||
],
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: inputController,
|
controller: inputController,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
value = value.replaceAll('Rp ', '').replaceAll('.', '');
|
validationInputValue(value);
|
||||||
double parseValue = double.parse(value);
|
|
||||||
if(value.isNotEmpty){
|
|
||||||
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
}else{
|
|
||||||
inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
@@ -98,30 +127,36 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text('Minimum Budget Rp1,000,000',
|
if(widget.minimumPrice != null)
|
||||||
style: TextStyle(
|
Text('Minimum ${NumberFormatter.numberCurrency(widget.minimumPrice, 'Rp ', 'id_ID')}',
|
||||||
color: ColorPalette.slate400,
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.w600
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if(widget.maximumPrice != null)
|
||||||
SizedBox(height: 16),
|
Text('Maximum ${NumberFormatter.numberCurrency(widget.maximumPrice, 'Rp ', 'id_ID')}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
NumericPad(onNumberSelected: (p0) {
|
NumericPad(onNumberSelected: (p0) {
|
||||||
String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', '');
|
String currentValue = inputController.text;
|
||||||
String getNumeric = p0;
|
|
||||||
if(p0.isNotEmpty){
|
if(p0.isNotEmpty){
|
||||||
if(checkIsZeroInput != '0'){
|
if(currentValue != '0'){
|
||||||
getNumeric = checkIsZeroInput + getNumeric;
|
currentValue = currentValue + p0;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
|
currentValue = currentValue.substring(0, currentValue.length - 1);
|
||||||
}
|
}
|
||||||
String formatNumeric = NumberFormatter.numberCurrency(
|
validationInputValue(currentValue);
|
||||||
double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
|
|
||||||
inputController.text = formatNumeric;
|
|
||||||
}),
|
}),
|
||||||
SizedBox(height: 8),
|
const SizedBox(height: 24),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -129,7 +164,7 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
},
|
},
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -137,6 +172,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -139,9 +139,8 @@ class TotalPaymentView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
RadioAgreement(
|
RadioAgreement(
|
||||||
isAgree: isAgree,
|
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: () {
|
onTap: () {
|
||||||
print('gagaga');
|
|
||||||
onTapAgree();
|
onTapAgree();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.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/component/take_picture_screen/take_picture_screen.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -94,10 +95,8 @@ class _DisplayPictureScreenState extends State<DisplayPictureScreen> {
|
|||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: CustomAppBar(
|
||||||
title: const Text('Preview'),
|
height: SizeConfig.height * .08, title: 'Preview'),
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
),
|
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:cims_apps/application/assets/path_assets.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/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart';
|
import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
@@ -27,7 +28,6 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
late String _takeContent;
|
late String _takeContent;
|
||||||
|
|
||||||
Future<void> changeFlash() async {
|
Future<void> changeFlash() async {
|
||||||
await _controller.setFlashMode(FlashMode.auto);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
isFlash = !isFlash;
|
isFlash = !isFlash;
|
||||||
});
|
});
|
||||||
@@ -44,6 +44,7 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
// Next, initialize the controller. This returns a Future.
|
// Next, initialize the controller. This returns a Future.
|
||||||
_initializeControllerFuture = _controller.initialize();
|
_initializeControllerFuture = _controller.initialize();
|
||||||
_takeContent = widget.takeContent;
|
_takeContent = widget.takeContent;
|
||||||
|
_controller.setFlashMode(isFlash ? FlashMode.torch : FlashMode.off);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -57,9 +58,10 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Fill this out in the next steps.
|
// Fill this out in the next steps.
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: CustomAppBar(
|
||||||
title: const Text('Registration'),
|
title: 'Registration',
|
||||||
actions: [
|
height: SizeConfig.height * .08,
|
||||||
|
trailing: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
changeFlash();
|
changeFlash();
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class StringUtils {
|
class StringUtils {
|
||||||
static bool emailValidation(String email) {
|
static bool emailValidation(String email) {
|
||||||
return RegExp(
|
return RegExp(
|
||||||
@@ -13,4 +18,24 @@ class StringUtils {
|
|||||||
return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})')
|
return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})')
|
||||||
.hasMatch(password);
|
.hasMatch(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String formatTime(DateTime? dateTime) {
|
||||||
|
if (dateTime != null) {
|
||||||
|
DateFormat formatter = DateFormat('HH:mm:ss');
|
||||||
|
return formatter.format(dateTime);
|
||||||
|
}
|
||||||
|
return '--:--:--';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iCopyToClipboard(BuildContext context,
|
||||||
|
{String? desc, required String text}) {
|
||||||
|
Clipboard.setData(ClipboardData(text: text));
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
.showSnackBar(SnackBar(
|
||||||
|
backgroundColor: ColorPalette.primary,
|
||||||
|
content: Text(desc ?? "Text copied to clipboard"),
|
||||||
|
))
|
||||||
|
.closed
|
||||||
|
.then((value) => ScaffoldMessenger.of(context).removeCurrentSnackBar());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,107 +6,120 @@ import 'package:cims_apps/application/theme/color_palette.dart';
|
|||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.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:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ModelDataBank {
|
||||||
|
final String? title, subtitle;
|
||||||
|
ModelDataBank(this.title, this.subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
class ConfirmBankAccount extends StatelessWidget {
|
class ConfirmBankAccount extends StatelessWidget {
|
||||||
const ConfirmBankAccount({Key? key}) : super(key: key);
|
const ConfirmBankAccount({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List listData = [
|
final listDataBank =
|
||||||
{'title': 'Bank Name', 'subtitle': 'Bank Mandiri'},
|
ModalRoute.of(context)!.settings.arguments as List<ModelDataBank>;
|
||||||
{'title': 'Account Number', 'subtitle': '123002212084'},
|
|
||||||
{'title': 'Account Owner Name', 'subtitle': 'Muhamad Rosyidin'},
|
return ChangeNotifierProvider(
|
||||||
{'title': 'Name on ID card', 'subtitle': 'Muhamad Rosyidin'},
|
create: (context) => SubmissionDataViewModel(),
|
||||||
];
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
toolbarHeight: 70,
|
toolbarHeight: 70,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
surfaceTintColor: Colors.white,
|
surfaceTintColor: Colors.white,
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const BackButtonView(),
|
const BackButtonView(),
|
||||||
const Text('Registration'),
|
const Text('Registration'),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SizeConfig.width * 0.1,
|
width: SizeConfig.width * 0.1,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
side: BorderSide(color: ColorPalette.slate200)),
|
side: BorderSide(color: ColorPalette.slate200)),
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: SizeConfig.height * .85,
|
height: SizeConfig.height * .85,
|
||||||
child: Column(
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
builder: (context, provider, child) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
return Column(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
const TextCaption(title: 'Bank account confirmation'),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
SizedBox(
|
children: [
|
||||||
height: SizeConfig.height * .6,
|
const TextCaption(title: 'Bank account confirmation'),
|
||||||
child: Column(
|
SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
height: SizeConfig.height * .6,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
...listData.map((e) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
...listDataBank.map((e) {
|
||||||
e['title'],
|
return Padding(
|
||||||
style: const TextStyle(
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
color: ColorPalette.slate400, fontSize: 16),
|
child: Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
e['subtitle'],
|
children: [
|
||||||
style: const TextStyle(
|
Text(
|
||||||
fontSize: 16,
|
e.title!,
|
||||||
color: ColorPalette.slate800,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w600),
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
e.subtitle!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
const ListTileView(
|
||||||
|
title:
|
||||||
|
'Make sure your data is correct as it will affect the disbursement process',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}).toList(),
|
Row(
|
||||||
const ListTileView(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
title:
|
children: [
|
||||||
'Make sure your data is correct as it will affect the disbursement process',
|
ButtonView(
|
||||||
),
|
name: 'Recheck',
|
||||||
],
|
isOutlined: true,
|
||||||
),
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Confirm',
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubmissionParent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
);
|
||||||
children: [
|
});
|
||||||
ButtonView(
|
|
||||||
name: 'Recheck',
|
|
||||||
isOutlined: true,
|
|
||||||
width: SizeConfig.width * .42,
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ButtonView(
|
|
||||||
name: 'Confirm',
|
|
||||||
width: SizeConfig.width * .42,
|
|
||||||
onPressed: () {
|
|
||||||
routePush(context, page: const SubmissionParent());
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,61 +63,98 @@ class SubmitBankAccount extends StatelessWidget {
|
|||||||
return SizedBox(
|
return SizedBox(
|
||||||
child: Consumer<SubmissionDataViewModel>(
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return SingleChildScrollView(
|
return SizedBox(
|
||||||
child: Column(
|
height: SizeConfig.height * .8,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Form(
|
||||||
children: [
|
key: provider.formKeySubmitDataBank,
|
||||||
const TextCaption(title: 'Input your bank account data'),
|
child: Column(
|
||||||
TextFormView(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
name: 'Bank Name',
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
hintText: 'Select bank',
|
children: [
|
||||||
readOnly: true,
|
const TextCaption(title: 'Input your bank account data'),
|
||||||
ctrl: provider.ctrlBankName,
|
TextFormView(
|
||||||
onTap: () {
|
name: 'Bank Name',
|
||||||
showSearchBank(provider.ctrlBankName);
|
hintText: 'Select bank',
|
||||||
},
|
readOnly: true,
|
||||||
suffixIcon: const Icon(
|
ctrl: provider.ctrlBankName,
|
||||||
Icons.keyboard_arrow_down_outlined,
|
onTap: () {
|
||||||
|
showSearchBank(provider.ctrlBankName);
|
||||||
|
},
|
||||||
|
suffixIcon: const Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
TextFormView(
|
||||||
TextFormView(
|
name: 'Account Number',
|
||||||
name: 'Account Number',
|
hintText: 'Input Account Number',
|
||||||
hintText: 'Input Account Number',
|
ctrl: provider.ctrlNoAccountBank,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
trailingTitleWidget: SizedBox(
|
validator: (value) {
|
||||||
width: 24,
|
if (value!.isEmpty) {
|
||||||
child: GestureDetector(
|
return 'Field must be filled';
|
||||||
onTap: () {
|
}
|
||||||
routePush(context, page: const GuideScreen());
|
return null;
|
||||||
},
|
},
|
||||||
child:
|
trailingTitleWidget: SizedBox(
|
||||||
const ImageView(image: PathAssets.iconQuestion),
|
width: 24,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context, page: const GuideScreen());
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
const ImageView(image: PathAssets.iconQuestion),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
TextFormView(
|
||||||
TextFormView(
|
name: 'Account Owner Name',
|
||||||
name: 'Account Owner Name',
|
hintText: 'Input Account Name',
|
||||||
hintText: 'Input Account Name',
|
ctrl: provider.ctrlNameAccountBank,
|
||||||
),
|
validator: (value) {
|
||||||
const Text(
|
if (value!.isEmpty) {
|
||||||
"Make sure the account you use is in your name, not someone else's",
|
return 'Field must be filled';
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: SizeConfig.height * .08),
|
|
||||||
ButtonView(
|
|
||||||
name: 'Next',
|
|
||||||
onPressed: () {
|
|
||||||
provider.next(context).then((value) {
|
|
||||||
if (value) {
|
|
||||||
routePush(context,
|
|
||||||
page: const ConfirmBankAccount());
|
|
||||||
}
|
}
|
||||||
});
|
return null;
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
],
|
const Text(
|
||||||
|
"Make sure the account you use is in your name, not someone else's",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: SizeConfig.height * .08),
|
||||||
|
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(),
|
||||||
|
arguments: values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
@@ -14,12 +14,12 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
height: SizeConfig.height,
|
height: SizeConfig.height * .8,
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
const Column(
|
||||||
children: [
|
children: [
|
||||||
ImageView(image: PathAssets.imgDataReport),
|
ImageView(image: PathAssets.imgDataReport),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@@ -48,7 +48,7 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
const Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
ImageView(
|
ImageView(
|
||||||
@@ -68,7 +68,7 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
ButtonView(
|
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/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
@@ -66,47 +67,55 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
|||||||
return ChangeNotifierProvider(
|
return ChangeNotifierProvider(
|
||||||
create: (context) => SubmissionDataViewModel(),
|
create: (context) => SubmissionDataViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return WillPopScope(
|
return PopScope(
|
||||||
onWillPop: () async {
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) async {
|
||||||
|
if (didPop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await routePush(context,
|
await routePush(context,
|
||||||
page: const BottomNavigationView(),
|
page: const BottomNavigationView(),
|
||||||
routeType: RouteType.pushReplace);
|
routeType: RouteType.pushReplace);
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: Consumer<SubmissionDataViewModel>(
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
height: SizeConfig.height * .1, title: 'Registration'),
|
height: SizeConfig.height * .1,
|
||||||
body: Stack(
|
title: 'Registration',
|
||||||
|
leading: BackButtonView(
|
||||||
|
onPress: () {
|
||||||
|
routePush(
|
||||||
|
context,
|
||||||
|
page: const BottomNavigationView(),
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
padding: const EdgeInsets.symmetric(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
horizontal: 16.0, vertical: 16.0),
|
||||||
children: [
|
child: Row(
|
||||||
Padding(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
padding: const EdgeInsets.symmetric(
|
children: List.generate(provider.stepAmount, (index) {
|
||||||
horizontal: 16.0, vertical: 16.0),
|
return _stepItem(
|
||||||
child: Row(
|
isCurrentStep:
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
provider.getCurrentStep == index + 1 ||
|
||||||
children:
|
provider.getCurrentStep - 1 > index,
|
||||||
List.generate(provider.stepAmount, (index) {
|
);
|
||||||
return _stepItem(
|
}),
|
||||||
isCurrentStep:
|
),
|
||||||
provider.getCurrentStep == index + 1 ||
|
),
|
||||||
provider.getCurrentStep - 1 > index,
|
Expanded(
|
||||||
);
|
child: SingleChildScrollView(
|
||||||
}),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
),
|
child: _content(provider.getCurrentStep),
|
||||||
),
|
),
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: _content(provider.getCurrentStep),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -176,79 +176,107 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Consumer<SubmissionDataViewModel>(
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Column(
|
return Form(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
key: provider.formKeySubmitIdCard,
|
||||||
children: [
|
child: Column(
|
||||||
const TextCaption(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
title: 'Check your ID card data for accuracy'),
|
children: [
|
||||||
TextFormView(
|
const TextCaption(
|
||||||
name: 'NIK',
|
title: 'Check your ID card data for accuracy'),
|
||||||
keyboardType: TextInputType.number,
|
TextFormView(
|
||||||
),
|
name: 'NIK',
|
||||||
TextFormView(name: 'Full Name'),
|
keyboardType: TextInputType.number,
|
||||||
DatePickerView(
|
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;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
DatePickerView(
|
||||||
name: 'Birth Date',
|
name: 'Birth Date',
|
||||||
ctrl: provider.ctrlBirthDate,
|
ctrl: provider.ctrlBirthDate,
|
||||||
maxDate: DateTime.now(),
|
maxDate: DateTime.now(),
|
||||||
isMultipleSelection: false,
|
isMultipleSelection: false,
|
||||||
enabled: true),
|
enabled: true,
|
||||||
photoDocument(provider),
|
validatorDate: (value) {
|
||||||
Container(
|
if (value!.isEmpty) {
|
||||||
width: SizeConfig.width,
|
return 'Field must be filled';
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
}
|
||||||
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
return null;
|
||||||
decoration: BoxDecoration(
|
},
|
||||||
color: ColorPalette.blue50,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(
|
|
||||||
color: ColorPalette.greyLights,
|
|
||||||
width: 1,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Row(
|
photoDocument(provider),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Container(
|
||||||
children: [
|
width: SizeConfig.width,
|
||||||
const ImageView(
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
image: PathAssets.iconShield,
|
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
width: 20,
|
decoration: BoxDecoration(
|
||||||
height: 22,
|
color: ColorPalette.blue50,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
color: ColorPalette.greyLights,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
const SizedBox(
|
),
|
||||||
width: 8,
|
child: Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
const Expanded(
|
children: [
|
||||||
child: Text(
|
const ImageView(
|
||||||
'Will my data be safe?',
|
image: PathAssets.iconShield,
|
||||||
style: TextStyle(
|
width: 20,
|
||||||
fontWeight: FontWeight.w600,
|
height: 22,
|
||||||
color: ColorPalette.primary,
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Will my data be safe?',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
onPressed: () {
|
||||||
onPressed: () {
|
bottomSheet();
|
||||||
bottomSheet();
|
},
|
||||||
},
|
icon: const Icon(
|
||||||
icon: const Icon(
|
Icons.arrow_forward_ios,
|
||||||
Icons.arrow_forward_ios,
|
color: ColorPalette.primary,
|
||||||
color: ColorPalette.primary,
|
size: 20,
|
||||||
size: 20,
|
),
|
||||||
),
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
ButtonView(
|
||||||
ButtonView(
|
name: 'Next',
|
||||||
name: 'Next',
|
onPressed: () async {
|
||||||
onPressed: () async {
|
if (provider.formKeySubmitIdCard.currentState!
|
||||||
await provider.next(context).then((value) {
|
.validate()) {
|
||||||
if (value) {
|
await provider.next(context).then((value) {
|
||||||
routePush(context, page: const SubmissionParent());
|
if (value) {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubmissionParent());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
},
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@@ -15,41 +15,70 @@ import 'package:provider/provider.dart';
|
|||||||
class SubmitEmail extends StatelessWidget {
|
class SubmitEmail extends StatelessWidget {
|
||||||
const SubmitEmail({Key? key}) : super(key: key);
|
const SubmitEmail({Key? key}) : super(key: key);
|
||||||
|
|
||||||
Widget _emailVerify() {
|
Widget _emailVerify(BuildContext context, SubmissionDataViewModel provider) {
|
||||||
return Column(
|
var textTheme = Theme.of(context).textTheme;
|
||||||
children: [
|
return Padding(
|
||||||
const ImageView(image: PathAssets.imgEmail),
|
padding: const EdgeInsets.all(24.0),
|
||||||
Align(
|
child: Column(
|
||||||
alignment: Alignment.center,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: RichText(
|
children: [
|
||||||
textAlign: TextAlign.center,
|
const TextCaption(title: 'Check your e-mail'),
|
||||||
text: TextSpan(children: [
|
const ImageView(image: PathAssets.imgEmail),
|
||||||
const TextSpan(
|
Align(
|
||||||
text:
|
alignment: Alignment.center,
|
||||||
'We have sent a verification link to your e-mail. \nPlease check your email for ',
|
child: RichText(
|
||||||
style: TextStyle(
|
textAlign: TextAlign.center,
|
||||||
color: Colors.black,
|
text: TextSpan(children: [
|
||||||
decoration: TextDecoration.none,
|
TextSpan(
|
||||||
|
text:
|
||||||
|
'We have sent a verification link to your e-mail. \nPlease check your email for ',
|
||||||
|
style: textTheme.displayMedium,
|
||||||
),
|
),
|
||||||
),
|
TextSpan(
|
||||||
TextSpan(
|
recognizer: TapGestureRecognizer()
|
||||||
recognizer: TapGestureRecognizer()..onTap = () {},
|
..onTap = () async {
|
||||||
text: 'verification',
|
await provider.next(context).then((value) {
|
||||||
style: const TextStyle(
|
if (value) {
|
||||||
color: Colors.blue,
|
routePush(context, page: const SubmissionParent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
text: 'verification',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
TextSpan(
|
||||||
const TextSpan(
|
text: ' to \ncontinue registration.',
|
||||||
text: ' to \ncontinue registration.',
|
style: textTheme.displayMedium,
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.black,
|
|
||||||
decoration: TextDecoration.none,
|
|
||||||
),
|
),
|
||||||
),
|
]),
|
||||||
]),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,45 +89,41 @@ class SubmitEmail extends StatelessWidget {
|
|||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return SingleChildScrollView(
|
return SizedBox(
|
||||||
child: Column(
|
height: SizeConfig.height * .78,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Form(
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
key: provider.formKeySubmitEmail,
|
||||||
children: [
|
child: Column(
|
||||||
!provider.isEmailVerify
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
? const TextCaption(title: 'Enter your e-mail')
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
: const TextCaption(title: 'Check your e-mail '),
|
children: [
|
||||||
!provider.isEmailVerify
|
const TextCaption(title: 'Enter your e-mail'),
|
||||||
? TextFormView(
|
TextFormView(
|
||||||
name: 'E-mail Address',
|
name: 'E-mail Address',
|
||||||
hintText: 'Input e-mail address',
|
hintText: 'Input e-mail address',
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value!.isEmpty) {
|
if (value!.isEmpty) {
|
||||||
return 'Filled cannot be empty';
|
return 'Filled cannot be empty';
|
||||||
} else if (!StringUtils.emailValidation(value)) {
|
} else if (!StringUtils.emailValidation(value)) {
|
||||||
return 'Format email wrong';
|
return 'Format email wrong';
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
},
|
|
||||||
// onTap: () {
|
|
||||||
// provider.submitEmail();
|
|
||||||
// },
|
|
||||||
)
|
|
||||||
: _emailVerify(),
|
|
||||||
SizedBox(height: SizeConfig.height * .42),
|
|
||||||
ButtonView(
|
|
||||||
name: 'Next',
|
|
||||||
onPressed: () async {
|
|
||||||
await provider.next(context).then((value) {
|
|
||||||
if (value) {
|
|
||||||
routePush(context, page: const SubmissionParent());
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
)
|
SizedBox(height: SizeConfig.height * .43),
|
||||||
],
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () async {
|
||||||
|
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/select_form/select_form_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.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/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/view/submission_data/submission_parent.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -17,12 +18,13 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return SingleChildScrollView(
|
return SizedBox(
|
||||||
|
height: SizeConfig.height * .78,
|
||||||
child: Form(
|
child: Form(
|
||||||
key: provider.formKeyPersonalData,
|
key: provider.formKeyPersonalData,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
const TextCaption(title: 'Your personal details'),
|
const TextCaption(title: 'Your personal details'),
|
||||||
SelectFormView(
|
SelectFormView(
|
||||||
@@ -31,6 +33,12 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
ctrl: provider.ctrlOccupation,
|
ctrl: provider.ctrlOccupation,
|
||||||
listItem: provider.listOccupation,
|
listItem: provider.listOccupation,
|
||||||
onSelect: (value) {},
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SelectFormView(
|
SelectFormView(
|
||||||
name: 'Income Level (IDR)',
|
name: 'Income Level (IDR)',
|
||||||
@@ -38,6 +46,12 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
ctrl: provider.ctrlIncome,
|
ctrl: provider.ctrlIncome,
|
||||||
listItem: provider.listIncome,
|
listItem: provider.listIncome,
|
||||||
onSelect: (value) {},
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SelectFormView(
|
SelectFormView(
|
||||||
name: 'Marital Status',
|
name: 'Marital Status',
|
||||||
@@ -45,6 +59,12 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
ctrl: provider.ctrlMarital,
|
ctrl: provider.ctrlMarital,
|
||||||
listItem: provider.listMarital,
|
listItem: provider.listMarital,
|
||||||
onSelect: (value) {},
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SelectFormView(
|
SelectFormView(
|
||||||
name: 'Source of Fund',
|
name: 'Source of Fund',
|
||||||
@@ -52,20 +72,28 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
ctrl: provider.ctrlSourceFund,
|
ctrl: provider.ctrlSourceFund,
|
||||||
listItem: provider.listSourceFund,
|
listItem: provider.listSourceFund,
|
||||||
onSelect: (value) {},
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Align(
|
// SizedBox(height: SizeConfig.height * .18),
|
||||||
alignment: Alignment.bottomCenter,
|
ButtonView(
|
||||||
child: ButtonView(
|
marginVertical: 0,
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
if (provider.formKeyPersonalData.currentState!
|
||||||
|
.validate()) {
|
||||||
await provider.next(context).then((value) {
|
await provider.next(context).then((value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: const SubmissionParent());
|
page: const SubmissionParent());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -24,26 +24,30 @@ class InitialSignature extends StatelessWidget {
|
|||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Column(
|
return SizedBox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
height: SizeConfig.height * .8,
|
||||||
children: [
|
child: Column(
|
||||||
const TextCaption(title: 'Draw your digital sign'),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const ImageView(image: PathAssets.frameSignature),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
const ListTileView(
|
children: [
|
||||||
title:
|
const TextCaption(title: 'Draw your digital sign'),
|
||||||
'Make sure the sign you draw is match with your ID Card'),
|
const ImageView(image: PathAssets.frameSignature),
|
||||||
SizedBox(height: SizeConfig.height * .07),
|
const ListTileView(
|
||||||
ButtonView(
|
title:
|
||||||
name: 'Next',
|
'Make sure the sign you draw is match with your ID Card'),
|
||||||
onPressed: () {
|
SizedBox(height: SizeConfig.height * .1),
|
||||||
provider.next(context).then((value) {
|
ButtonView(
|
||||||
if (value) {
|
name: 'Next',
|
||||||
routePush(context, page: const SubmitSignature());
|
onPressed: () {
|
||||||
}
|
provider.next(context).then((value) {
|
||||||
});
|
if (value) {
|
||||||
},
|
routePush(context, page: const SubmitSignature());
|
||||||
)
|
}
|
||||||
],
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:cims_apps/application/component/select_form/select_form_view.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:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@@ -14,11 +15,16 @@ class SubmissionDataViewModel extends ChangeNotifier {
|
|||||||
bool _isEmailVerify = false;
|
bool _isEmailVerify = false;
|
||||||
bool get isEmailVerify => _isEmailVerify;
|
bool get isEmailVerify => _isEmailVerify;
|
||||||
var formKeyPersonalData = GlobalKey<FormState>();
|
var formKeyPersonalData = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitEmail = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitIdCard = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitDataBank = GlobalKey<FormState>();
|
||||||
TextEditingController ctrlOccupation = TextEditingController();
|
TextEditingController ctrlOccupation = TextEditingController();
|
||||||
TextEditingController ctrlIncome = TextEditingController();
|
TextEditingController ctrlIncome = TextEditingController();
|
||||||
TextEditingController ctrlMarital = TextEditingController();
|
TextEditingController ctrlMarital = TextEditingController();
|
||||||
TextEditingController ctrlSourceFund = TextEditingController();
|
TextEditingController ctrlSourceFund = TextEditingController();
|
||||||
TextEditingController ctrlBankName = TextEditingController();
|
TextEditingController ctrlBankName = TextEditingController();
|
||||||
|
TextEditingController ctrlNameAccountBank = TextEditingController();
|
||||||
|
TextEditingController ctrlNoAccountBank = TextEditingController();
|
||||||
TextEditingController ctrlBankNameSearch = TextEditingController();
|
TextEditingController ctrlBankNameSearch = TextEditingController();
|
||||||
TextEditingController ctrlBirthDate = TextEditingController();
|
TextEditingController ctrlBirthDate = TextEditingController();
|
||||||
int step = 1;
|
int step = 1;
|
||||||
@@ -120,4 +126,21 @@ class SubmissionDataViewModel extends ChangeNotifier {
|
|||||||
valueBank = value;
|
valueBank = value;
|
||||||
notifyListeners();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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/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/goal_investing_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
|
||||||
import 'package:cims_apps/application/component/risk_profile.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/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/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/step_invest_plan/options_starting_invest.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
@@ -46,33 +42,32 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
height: SizeConfig.height * 0.08,
|
height: SizeConfig.height * 0.08,
|
||||||
title: 'Investment Plan',
|
title: 'Investment Plan',
|
||||||
leading: SizedBox(),
|
leading: const SizedBox(),
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
RiskProfile(
|
const RiskProfile(
|
||||||
totalScore: 26,
|
totalScore: 26,
|
||||||
rowSuitableProduct: true
|
rowSuitableProduct: true
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 32,
|
height: 32,
|
||||||
),
|
),
|
||||||
Text('Your Goal in Investing',
|
const Text('Your Goal in Investing',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
fontSize: 18
|
fontSize: 18
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
GoalInvestingView(
|
GoalInvestingView(
|
||||||
onListSelected: (p0) {
|
onListSelected: (p0) {
|
||||||
print(p0);
|
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
@@ -103,7 +98,7 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("It's time to invest",
|
const Text("It's time to invest",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
@@ -113,17 +108,20 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
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(
|
InputInvestmentView(
|
||||||
selectedPlan: text,
|
currentPlan: text,
|
||||||
|
changePlan: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
nextMove: (value) {
|
nextMove: (value) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||||
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
|
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -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/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.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/redeem_product.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.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 = [
|
List<PortfolioProduct> listProduct = [
|
||||||
PortfolioProduct(
|
PortfolioProduct(
|
||||||
name: 'Gemilang Dana Kas Maxima',
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
type: '',
|
type: 'Money Market',
|
||||||
yield: 8.17,
|
yield: 8.17,
|
||||||
priceUnit: 2600.79,
|
priceUnit: 2600.79,
|
||||||
funds: 6300000),
|
funds: 6300000,
|
||||||
|
totalUnit: 14520
|
||||||
|
),
|
||||||
PortfolioProduct(
|
PortfolioProduct(
|
||||||
name: 'Gemilang Dana Likuid',
|
name: 'Gemilang Dana Likuid',
|
||||||
type: '',
|
type: 'Sharia',
|
||||||
yield: 6.42,
|
yield: 6.42,
|
||||||
priceUnit: 1600.79,
|
priceUnit: 1600.79,
|
||||||
funds: 2340000),
|
funds: 2340000,
|
||||||
|
totalUnit: 232,
|
||||||
|
),
|
||||||
PortfolioProduct(
|
PortfolioProduct(
|
||||||
name: 'Gemilang Income Fund',
|
name: 'Gemilang Income Fund',
|
||||||
type: '',
|
type: 'Bonds',
|
||||||
yield: 8.17,
|
yield: 8.17,
|
||||||
priceUnit: 2600.79,
|
priceUnit: 2600.79,
|
||||||
funds: 6300000)
|
funds: 6300000,
|
||||||
|
totalUnit: 2450,
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
return MultiProvider(
|
return ChangeNotifierProvider(
|
||||||
providers: [
|
create: (context) => RedeemProductViewModel(),
|
||||||
ChangeNotifierProvider(create: (context) => RedeemProductViewModel())
|
|
||||||
],
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
body: SizedBox(
|
body: SizedBox(
|
||||||
@@ -100,19 +105,20 @@ class PortfolioDetailView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 24,),
|
const SizedBox(height: 24,),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ClipRRect(
|
child: Container(
|
||||||
borderRadius: BorderRadius.circular(0),
|
decoration: BoxDecoration(
|
||||||
child: Container(
|
borderRadius: BorderRadius.circular(12),
|
||||||
decoration: BoxDecoration(
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(12),
|
),
|
||||||
color: Colors.white,
|
child: Consumer<RedeemProductViewModel>(
|
||||||
),
|
builder: (context, provider, child) {
|
||||||
child: ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
children: [
|
children: listProduct.asMap().entries.map((e) {
|
||||||
cardPortfolio(context)
|
return cardPortfolio(context, e.value);
|
||||||
],
|
}).toList(),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -125,7 +131,7 @@ class PortfolioDetailView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget cardPortfolio(context) {
|
Widget cardPortfolio(context, PortfolioProduct product) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -155,19 +161,19 @@ class PortfolioDetailView extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
TextTitle(title: product.name ?? '', fontSize: 16,),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(6),
|
padding: const EdgeInsets.all(6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(40),
|
borderRadius: BorderRadius.circular(40),
|
||||||
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
color: ColorPalette.investTypeBgColor[product.type!]?.withOpacity(0.5) ?? Colors.white,
|
||||||
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor[product.type!]?.withOpacity(0.4) ?? Colors.white)
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Money Market' ?? '',
|
product.type ?? '',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.investTypeColor['Money Market'],
|
color: ColorPalette.investTypeColor[product.type!],
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -187,8 +193,8 @@ class PortfolioDetailView extends StatelessWidget {
|
|||||||
rowDescription('Present Value', 'Rp2.660.706', fontWeight: FontWeight.w700),
|
rowDescription('Present Value', 'Rp2.660.706', fontWeight: FontWeight.w700),
|
||||||
rowDescription('Investment Capital', 'Rp2.660.706'),
|
rowDescription('Investment Capital', 'Rp2.660.706'),
|
||||||
rowDescription('Advantages', 'Rp2.660.706'),
|
rowDescription('Advantages', 'Rp2.660.706'),
|
||||||
rowDescription('Purchase Price', 'Rp1.500,57'),
|
rowDescription('Purchase Price', NumberFormatter.numberCurrency(product.priceUnit, 'Rp ', 'id_ID')),
|
||||||
rowDescription('Number of Units', '14.002'),
|
rowDescription('Number of Units', '${product.totalUnit ?? 0}'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16,),
|
const SizedBox(height: 16,),
|
||||||
@@ -206,6 +212,7 @@ class PortfolioDetailView extends StatelessWidget {
|
|||||||
borderColor: ColorPalette.red600,
|
borderColor: ColorPalette.red600,
|
||||||
textColor: ColorPalette.red600,
|
textColor: ColorPalette.red600,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
Provider.of<RedeemProductViewModel>(context, listen: false).setProduct(product);
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
|
@@ -4,6 +4,7 @@ import 'package:cims_apps/application/assets/path_assets.dart';
|
|||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||||
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
@@ -82,98 +83,33 @@ class _ChangeAmountState extends State<ChangeAmount> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(height: 1, color: ColorPalette.slate200,),
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
Padding(
|
Column(
|
||||||
padding: EdgeInsets.all(24),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Padding(
|
||||||
children: [
|
padding: EdgeInsets.all(24),
|
||||||
cardProduct(),
|
child: cardProduct()
|
||||||
SizedBox(height: 24),
|
),
|
||||||
TextField(
|
InputInvestmentView(
|
||||||
controller: amountController,
|
minimumPrice: (provider.getCurrentProduct.priceUnit! * 1).toInt(),
|
||||||
textAlign: TextAlign.center,
|
maximumPrice: (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(),
|
||||||
style: const TextStyle(
|
currentPrice: provider.getAmount!.toInt(),
|
||||||
fontSize: 28,
|
nextMove: (value) {
|
||||||
fontWeight: FontWeight.w600,
|
String formatValueInput = value.replaceAll('Rp ', '').replaceAll('.', '');
|
||||||
color: ColorPalette.slate800
|
provider.setAmount(double.parse(formatValueInput));
|
||||||
),
|
Navigator.pop(context);
|
||||||
keyboardType: TextInputType.number,
|
showModalBottomSheet(
|
||||||
onChanged: (value) {
|
context: context,
|
||||||
value = value.replaceAll('Rp ', '').replaceAll('.', '');
|
isScrollControlled: true,
|
||||||
double parseValue = double.parse(value);
|
builder: (context) {
|
||||||
if(value.isNotEmpty){
|
return const RedeemProduct();
|
||||||
amountController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
},
|
||||||
}else{
|
);
|
||||||
amountController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
|
},
|
||||||
}
|
)
|
||||||
},
|
],
|
||||||
decoration: const InputDecoration(
|
),
|
||||||
enabledBorder: UnderlineInputBorder(
|
SizedBox(height: 16,)
|
||||||
borderSide: BorderSide(
|
|
||||||
color: ColorPalette.primary,
|
|
||||||
width: 2
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 12),
|
|
||||||
Text(
|
|
||||||
'Min Redeem: ${(NumberFormatter.numberCurrency(10000, 'Rp ', 'id_ID', decimalDigits: 0))}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate400,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'Max Redeem: ${(NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0))}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate400,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
NumericPad(onNumberSelected: (p0) {
|
|
||||||
String checkIsZeroInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', '');
|
|
||||||
String getNumeric = p0;
|
|
||||||
|
|
||||||
if(p0.isNotEmpty){
|
|
||||||
if(checkIsZeroInput != '0'){
|
|
||||||
getNumeric = checkIsZeroInput + getNumeric;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
|
|
||||||
}
|
|
||||||
if(getNumeric.isEmpty){
|
|
||||||
getNumeric = '0';
|
|
||||||
}
|
|
||||||
if(double.parse(getNumeric) >= provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!){
|
|
||||||
getNumeric = (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toString();
|
|
||||||
}
|
|
||||||
String formatNumeric = NumberFormatter.numberCurrency(
|
|
||||||
double.parse(getNumeric).toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
amountController.text = formatNumeric;
|
|
||||||
}),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
ButtonView(
|
|
||||||
name: 'Confirm',
|
|
||||||
textSize: 20,
|
|
||||||
marginVertical: 0,
|
|
||||||
onPressed: () {
|
|
||||||
String formatValueInput = amountController.text.replaceAll('Rp ', '').replaceAll('.', '');
|
|
||||||
provider.setAmount(double.parse(formatValueInput));
|
|
||||||
Navigator.pop(context);
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (context) {
|
|
||||||
return const RedeemProduct();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,7 @@ class _RedeemProductState extends State<RedeemProduct> {
|
|||||||
create: (context) => RedeemProductViewModel(),
|
create: (context) => RedeemProductViewModel(),
|
||||||
child: Consumer<RedeemProductViewModel>(
|
child: Consumer<RedeemProductViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
double amount = provider.getAmount ?? provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!;
|
amountController.text = NumberFormatter.numberCurrency(provider.getAmount!.toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
amountController.text = NumberFormatter.numberCurrency(amount.toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -76,8 +75,8 @@ class _RedeemProductState extends State<RedeemProduct> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
segmentAmount(
|
segmentAmount(
|
||||||
context,
|
context,
|
||||||
provider.getAmount ?? provider.getCurrentProduct.priceUnit! * (provider.getCurrentProduct.totalUnit! / 2.0),
|
provider.getAmount!,
|
||||||
provider.getUnit ?? provider.getCurrentProduct.totalUnit! / 2.0,
|
provider.getUnit!,
|
||||||
(value) {
|
(value) {
|
||||||
provider.setUnit(value);
|
provider.setUnit(value);
|
||||||
},
|
},
|
||||||
|
@@ -61,6 +61,8 @@ class RedeemProductViewModel extends ChangeNotifier {
|
|||||||
|
|
||||||
void setProduct(PortfolioProduct product) {
|
void setProduct(PortfolioProduct product) {
|
||||||
currentProduct = product;
|
currentProduct = product;
|
||||||
|
amount = product.priceUnit! * (product.totalUnit! / 2.0);
|
||||||
|
unit = (product.totalUnit! / 2.0);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -55,32 +55,43 @@ class SelectGoalInvesting extends StatelessWidget {
|
|||||||
create: (context) => ProductViewModel(),
|
create: (context) => ProductViewModel(),
|
||||||
child: Consumer<ProductViewModel>(
|
child: Consumer<ProductViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return InputInvestmentView(
|
return Padding(
|
||||||
selectedPlan: p0,
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
nextMove: (value) {
|
child: InputInvestmentView(
|
||||||
Navigator.pop(context);
|
currentPlan: p0,
|
||||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
changePlan: () {
|
||||||
showModalBottomSheet(
|
Navigator.pop(context);
|
||||||
context: context,
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
context: context,
|
||||||
builder: (context) =>
|
isScrollControlled: true,
|
||||||
ChangeNotifierProvider(
|
builder: (context) => SelectGoalInvesting(),
|
||||||
create: (context) => ProductViewModel(),
|
);
|
||||||
child: Consumer<ProductViewModel>(
|
},
|
||||||
builder: (context, provider, child) {
|
nextMove: (value) {
|
||||||
return TotalPaymentView(
|
Navigator.pop(context);
|
||||||
listProduct: [
|
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||||
provider.getSelectedProduct
|
showModalBottomSheet(
|
||||||
],
|
context: context,
|
||||||
totalInvest: formatIntParse,
|
isScrollControlled: true,
|
||||||
isAgree: provider.isAgree,
|
builder: (context) =>
|
||||||
onTapAgree: provider.setAgree,
|
ChangeNotifierProvider(
|
||||||
);
|
create: (context) => ProductViewModel(),
|
||||||
}
|
child: Consumer<ProductViewModel>(
|
||||||
),
|
builder: (context, provider, child) {
|
||||||
)
|
return TotalPaymentView(
|
||||||
);
|
listProduct: [
|
||||||
},
|
provider.getSelectedProduct
|
||||||
|
],
|
||||||
|
totalInvest: formatIntParse,
|
||||||
|
isAgree: provider.isAgree,
|
||||||
|
onTapAgree: provider.setAgree,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
8
lib/features/profile/model/list_menu_model.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ListMenuModel {
|
||||||
|
final String title, pathAsset;
|
||||||
|
final Widget page;
|
||||||
|
ListMenuModel(
|
||||||
|
{required this.title, required this.pathAsset, required this.page});
|
||||||
|
}
|
@@ -1,5 +1,8 @@
|
|||||||
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/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/profile/model/list_menu_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ProfileView extends StatelessWidget {
|
class ProfileView extends StatelessWidget {
|
||||||
@@ -7,8 +10,110 @@ class ProfileView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
List<ListMenuModel> listMenuGeneral = [
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Personal Data',
|
||||||
|
pathAsset: PathAssets.iconProfile,
|
||||||
|
page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Change Password',
|
||||||
|
pathAsset: PathAssets.iconLock,
|
||||||
|
page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Add Card', pathAsset: PathAssets.iconCard, page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Settings',
|
||||||
|
pathAsset: PathAssets.iconSetting,
|
||||||
|
page: Container()),
|
||||||
|
];
|
||||||
|
|
||||||
|
List<ListMenuModel> listMenuPreferences = [
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'FAQs', pathAsset: PathAssets.iconChat, page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Log Out',
|
||||||
|
pathAsset: PathAssets.iconLogout,
|
||||||
|
page: Container()),
|
||||||
|
];
|
||||||
|
TextStyle textStyle = const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget cardContent(
|
||||||
|
{required String title, required List<ListMenuModel> listMenu}) {
|
||||||
|
return Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12))),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title),
|
||||||
|
...listMenu.map((e) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(e.title),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: ImageView(
|
||||||
|
image: e.pathAsset, width: SizeConfig.width * .08),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios,
|
||||||
|
color: ColorPalette.slate400),
|
||||||
|
onTap: () {
|
||||||
|
// routePush(context, page: e.page);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(height: SizeConfig.height * .08, title: 'Profile'),
|
appBar: null,
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
ImageView(image: PathAssets.bgProfile, width: SizeConfig.width),
|
||||||
|
Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.only(bottom: 60.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('Profile', style: textStyle),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 40.0, bottom: 8.0),
|
||||||
|
child: ImageView(
|
||||||
|
image: PathAssets.imgCatOutlined,
|
||||||
|
width: SizeConfig.width * .28,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Muhamad Rosyidin',
|
||||||
|
style: textStyle.copyWith(fontSize: 24)),
|
||||||
|
Text('Investor Conservative',
|
||||||
|
style: textStyle.copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: ColorPalette.green400,
|
||||||
|
)),
|
||||||
|
SizedBox(height: SizeConfig.height * .02),
|
||||||
|
cardContent(title: 'General', listMenu: listMenuGeneral),
|
||||||
|
SizedBox(height: SizeConfig.height * .03),
|
||||||
|
cardContent(
|
||||||
|
title: 'Preference', listMenu: listMenuPreferences),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
lib/features/transaction/view/cancel_view.dart
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
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/route/route.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/view/subscribe_detail_view.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.listCancelTransaction.isEmpty)
|
||||||
|
EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
...provider.listCancelTransaction.map((e) {
|
||||||
|
return CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconEducation,
|
||||||
|
type: 'Education',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'cancel',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
53
lib/features/transaction/view/done_view.dart
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
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/route/route.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/view/subscribe_detail_view.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.listDoneTransaction.isEmpty)
|
||||||
|
EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
...provider.listDoneTransaction.map((e) {
|
||||||
|
return CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconEducation,
|
||||||
|
type: 'Education',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'done',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
50
lib/features/transaction/view/onprocess_view.dart
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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/route/route.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/view/subscribe_detail_view.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(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconHome,
|
||||||
|
type: 'Home',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'on process',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
516
lib/features/transaction/view/subscribe_detail_view.dart
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/list_tile/list_tile_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SubscribeDetailView extends StatelessWidget {
|
||||||
|
final String type;
|
||||||
|
const SubscribeDetailView({Key? key, required this.type}) : super(key: key);
|
||||||
|
|
||||||
|
Widget _stepper(
|
||||||
|
TextTheme textTheme, {
|
||||||
|
required String description,
|
||||||
|
String? date,
|
||||||
|
time,
|
||||||
|
bool isActive = false,
|
||||||
|
bool isDone = false,
|
||||||
|
bool isLast = false,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0, left: 16.0),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 2.0, top: 8.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle_rounded,
|
||||||
|
size: 10,
|
||||||
|
color: isDone
|
||||||
|
? ColorPalette.primary
|
||||||
|
: isActive
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!isLast)
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints.expand(
|
||||||
|
height: SizeConfig.width * .2, width: 0.0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: VerticalDivider(
|
||||||
|
color:
|
||||||
|
isDone ? ColorPalette.primary : ColorPalette.slate400,
|
||||||
|
thickness: 2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
description,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: isDone
|
||||||
|
? Colors.black87
|
||||||
|
: isActive
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
isDone
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Text(date ?? ''),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 6,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(time ?? ''),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _listProduct(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .1,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Gemilang Dana Kas Maxima',
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0, vertical: 2.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorPalette.purple100,
|
||||||
|
border: Border.all(
|
||||||
|
width: 1,
|
||||||
|
color: ColorPalette.purple,
|
||||||
|
),
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(24)),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'Money Market',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.purple500,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Investment Amount'),
|
||||||
|
Text(
|
||||||
|
'Rp 2.000.000',
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorPalette.slate200,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _cardVA(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(top: 16.0, bottom: 8.0),
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: SizeConfig.height * .02),
|
||||||
|
RichText(
|
||||||
|
text: const TextSpan(children: [
|
||||||
|
TextSpan(
|
||||||
|
text: 'Transfer to ',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: 'ABC Virtual Account',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
SizedBox(height: SizeConfig.height * .01),
|
||||||
|
const Text(
|
||||||
|
'Ferdy Maulana',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTileView(
|
||||||
|
title: '8785 0000 3165 5512',
|
||||||
|
prefixIcon: const SizedBox(),
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
margin: const EdgeInsets.only(top: 8.0, bottom: 8.0),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: ColorPalette.primary),
|
||||||
|
suffixIcon: ButtonView(
|
||||||
|
name: 'Copy',
|
||||||
|
width: SizeConfig.width * .3,
|
||||||
|
height: SizeConfig.height * .052,
|
||||||
|
sizeBorderRadius: 8.0,
|
||||||
|
widthPrefix: 8.0,
|
||||||
|
marginVertical: 10.0,
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.file_copy_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
StringUtils.iCopyToClipboard(
|
||||||
|
context,
|
||||||
|
text: '8785 0000 3165 5512',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(color: ColorPalette.slate200),
|
||||||
|
const Text(
|
||||||
|
'Amount to be transferred',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTileView(
|
||||||
|
title: 'Rp 10.000.000',
|
||||||
|
prefixIcon: const SizedBox(),
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
margin: const EdgeInsets.only(top: 8.0),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: ColorPalette.primary),
|
||||||
|
suffixIcon: ButtonView(
|
||||||
|
name: 'Copy',
|
||||||
|
width: SizeConfig.width * .3,
|
||||||
|
height: SizeConfig.height * .052,
|
||||||
|
sizeBorderRadius: 8.0,
|
||||||
|
widthPrefix: 8.0,
|
||||||
|
marginVertical: 10.0,
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.file_copy_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
StringUtils.iCopyToClipboard(
|
||||||
|
context,
|
||||||
|
text: '10.000.000',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _cardContent(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
List mySteps = const [
|
||||||
|
{
|
||||||
|
'desc': 'Payment Being Verified',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': true,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Successful Payment',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': true,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Investment Manager Verification',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Successful Purchase',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.access_time, color: ColorPalette.slate400),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text('Waiting for Payment'),
|
||||||
|
),
|
||||||
|
Text('23:56:42', style: textTheme.headlineSmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
type == 'virtual' ? _cardVA(context) : const SizedBox(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
child: Text('Purchase Details', style: textTheme.headlineSmall),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: ExpansionTile(
|
||||||
|
shape: ShapeBorder.lerp(
|
||||||
|
const StadiumBorder(side: BorderSide.none),
|
||||||
|
InputBorder.none,
|
||||||
|
0),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.iconEducation,
|
||||||
|
width: SizeConfig.width * .08,
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 8.0),
|
||||||
|
child: Text('Education'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 40.0),
|
||||||
|
child: Text('3 Subscriptions', style: textTheme.bodyMedium),
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
_listProduct(context),
|
||||||
|
_listProduct(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...mySteps.map((e) {
|
||||||
|
return _stepper(
|
||||||
|
textTheme,
|
||||||
|
description: '${e['desc']}',
|
||||||
|
date: e['date'],
|
||||||
|
time: e['time'],
|
||||||
|
isActive: e['isActive'],
|
||||||
|
isDone: e['isDone'],
|
||||||
|
isLast: e['isLast'],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
// padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: ExpansionTile(
|
||||||
|
shape: ShapeBorder.lerp(
|
||||||
|
const StadiumBorder(side: BorderSide.none),
|
||||||
|
InputBorder.none,
|
||||||
|
0),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: Text('When Is My Purchase Complete?')),
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgExpandPurchase,
|
||||||
|
width: SizeConfig.width * .15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: SizedBox(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(height: SizeConfig.height * .05),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
BackButtonView(
|
||||||
|
onPress: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 80.0),
|
||||||
|
child: Text(
|
||||||
|
'Subscribe Detail',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
type == 'virtual'
|
||||||
|
? const Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
'Virtual Account',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .08,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Text(
|
||||||
|
type == 'virtual' ? 'ABC' : 'Shopping Pay',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(top: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'No.Subscribe : ',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'PI9393084SDMI1',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(top: 32.0),
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(24),
|
||||||
|
topRight: Radius.circular(24)),
|
||||||
|
),
|
||||||
|
child: _cardContent(context)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -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/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/material.dart';
|
||||||
|
import 'package:flutter_toggle_tab/flutter_toggle_tab.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class TransactionView extends StatelessWidget {
|
class TransactionView extends StatelessWidget {
|
||||||
const TransactionView({Key? key}) : super(key: key);
|
const TransactionView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
List<Tab> textTabs = const [
|
||||||
appBar: CustomAppBar(height: SizeConfig.height * 0.08, title: 'Transaction'),
|
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(
|
||||||
|
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),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
49
lib/features/transaction/view/waiting_view.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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/route/route.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/view/subscribe_detail_view.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: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'normal',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
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 = [1];
|
||||||
|
List listDoneTransaction = [];
|
||||||
|
List listCancelTransaction = [];
|
||||||
|
}
|
114
lib/main.dart
@@ -20,68 +20,66 @@ class MyApp extends StatelessWidget {
|
|||||||
title: 'CIMS',
|
title: 'CIMS',
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: const AppBarTheme(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: Colors.black,
|
||||||
titleTextStyle: TextStyle(
|
titleTextStyle: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
)),
|
||||||
|
fontFamily: 'Manrope',
|
||||||
|
scaffoldBackgroundColor: Colors.white,
|
||||||
|
textTheme: const TextTheme(
|
||||||
|
displaySmall: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
)),
|
),
|
||||||
fontFamily: 'Manrope',
|
displayMedium: TextStyle(
|
||||||
scaffoldBackgroundColor: Colors.white,
|
fontSize: 16,
|
||||||
textTheme: const TextTheme(
|
fontWeight: FontWeight.w600,
|
||||||
displaySmall: TextStyle(
|
color: ColorPalette.slate800,
|
||||||
fontSize: 14,
|
),
|
||||||
fontWeight: FontWeight.w500,
|
displayLarge: TextStyle(
|
||||||
color: ColorPalette.slate800,
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
bodyMedium: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
bodyLarge: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
headlineSmall: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
headlineLarge: TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
displayMedium: TextStyle(
|
colorScheme: const ColorScheme.light().copyWith(
|
||||||
fontSize: 16,
|
primary: const Color(0xff2563EB),
|
||||||
fontWeight: FontWeight.w600,
|
onPrimary: const Color(0xFFFF9130),
|
||||||
color: ColorPalette.slate800,
|
secondary: const Color(0xFFFECDA6),
|
||||||
|
onBackground: const Color(0xFFA9A9A9),
|
||||||
),
|
),
|
||||||
displayLarge: TextStyle(
|
bottomSheetTheme: const BottomSheetThemeData(
|
||||||
fontSize: 16,
|
backgroundColor: Colors.white, surfaceTintColor: Colors.white)
|
||||||
fontWeight: FontWeight.bold,
|
// useMaterial3: true,
|
||||||
color: ColorPalette.slate800,
|
|
||||||
),
|
),
|
||||||
bodyMedium: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: ColorPalette.slate500,
|
|
||||||
),
|
|
||||||
bodyLarge: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: ColorPalette.slate500,
|
|
||||||
),
|
|
||||||
headlineSmall: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: ColorPalette.slate800,
|
|
||||||
),
|
|
||||||
headlineLarge: TextStyle(
|
|
||||||
fontSize: 28,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: ColorPalette.slate800,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
colorScheme: const ColorScheme.light().copyWith(
|
|
||||||
primary: const Color(0xff2563EB),
|
|
||||||
onPrimary: const Color(0xFFFF9130),
|
|
||||||
secondary: const Color(0xFFFECDA6),
|
|
||||||
onBackground: const Color(0xFFA9A9A9),
|
|
||||||
),
|
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
surfaceTintColor: Colors.white
|
|
||||||
)
|
|
||||||
// useMaterial3: true,
|
|
||||||
),
|
|
||||||
initialRoute: initialRoute,
|
initialRoute: initialRoute,
|
||||||
onGenerateRoute: generateRoutes,
|
onGenerateRoute: generateRoutes,
|
||||||
navigatorObservers: [
|
navigatorObservers: [
|
||||||
|
@@ -259,6 +259,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
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:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@@ -53,6 +53,7 @@ dependencies:
|
|||||||
shared_preferences: ^2.2.2
|
shared_preferences: ^2.2.2
|
||||||
calendar_date_picker2: ^0.5.3
|
calendar_date_picker2: ^0.5.3
|
||||||
google_sign_in: ^6.2.1
|
google_sign_in: ^6.2.1
|
||||||
|
flutter_toggle_tab: ^1.4.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|