13 Commits

34 changed files with 1259 additions and 570 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
assets/icons/icon-fund.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
assets/icons/icon-home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
assets/icons/icon-shop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -49,11 +49,16 @@ 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 iconCat = 'assets/icons/icon-cat.png'; static const String iconCat = 'assets/icons/icon-cat.png';
static const String iconProfile = 'assets/icons/icon-profile.png'; static const String iconProfile = 'assets/icons/icon-profile.png';
@@ -62,6 +67,12 @@ class PathAssets {
static const String iconSetting = 'assets/icons/icon-setting.png'; static const String iconSetting = 'assets/icons/icon-setting.png';
static const String iconFaqs = 'assets/icons/icon-faqs.png'; static const String iconFaqs = 'assets/icons/icon-faqs.png';
static const String iconLogout = 'assets/icons/icon-logout.png'; static const String iconLogout = 'assets/icons/icon-logout.png';
static const String iconEducation = 'assets/icons/icon-education.png';
static const String iconFund = 'assets/icons/icon-fund.png';
static const String iconHome = 'assets/icons/icon-home.png';
static const String iconShop = 'assets/icons/icon-shop.png';
static const String iconGadgetOutline =
'assets/icons/icon-gadget-outline.png';
/// IMAGE /// IMAGE
static const String imgSplashLogo = 'assets/images/splash-logo.png'; static const String imgSplashLogo = 'assets/images/splash-logo.png';
@@ -96,11 +107,14 @@ class PathAssets {
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 imgDashboardProfile = static const String imgDashboardProfile =
'assets/images/img-dashboard-profile.png'; 'assets/images/img-dashboard-profile.png';
static const String imgEmptyTransaction =
'assets/images/img-empty-transaction.png';
static const Map<String, String> goalInvestIcon = { static const Map<String, String> goalInvestIcon = {
'Education': iconToga, 'Education': iconToga,

View File

@@ -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),
),
],
),
],
)),
],
),
),
);
}
}

View File

@@ -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,
),
],
),
),
);
}
}

View File

@@ -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(

View File

@@ -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();

View File

@@ -190,6 +190,18 @@ class TextFormView extends StatelessWidget {
color: focusedBorderColor ?? ColorPalette.greyBorder, color: focusedBorderColor ?? ColorPalette.greyBorder,
), ),
), ),
errorBorder: OutlineInputBorder(
borderRadius: _borderRadius,
borderSide: BorderSide(
color: ColorPalette.red600
)
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: _borderRadius,
borderSide: BorderSide(
color: ColorPalette.red600
)
),
border: OutlineInputBorder(borderRadius: _borderRadius), border: OutlineInputBorder(borderRadius: _borderRadius),
suffixIcon: suffixIcon, suffixIcon: suffixIcon,
prefixIcon: prefixIcon, prefixIcon: prefixIcon,

View File

@@ -1,3 +1,5 @@
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 +15,12 @@ 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 '--:--:--';
}
} }

View File

@@ -52,7 +52,7 @@ class PhoneNumberView extends StatelessWidget {
width: SizeConfig.width * .23, width: SizeConfig.width * .23,
padding: padding:
const EdgeInsets.symmetric(horizontal: 16.0), const EdgeInsets.symmetric(horizontal: 16.0),
margin: const EdgeInsets.only(right: 16), margin: const EdgeInsets.only(right: 16, left: 1, top: 1, bottom: 1),
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: ColorPalette.grey, color: ColorPalette.grey,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(

View File

@@ -6,19 +6,26 @@ import 'package:cims_apps/application/theme/color_palette.dart';
import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/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,
@@ -42,7 +49,9 @@ class ConfirmBankAccount extends StatelessWidget {
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>(
builder: (context, provider, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -53,7 +62,7 @@ class ConfirmBankAccount extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
...listData.map((e) { ...listDataBank.map((e) {
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: Column( child: Column(
@@ -61,12 +70,13 @@ class ConfirmBankAccount extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
e['title'], e.title!,
style: const TextStyle( style: const TextStyle(
color: ColorPalette.slate400, fontSize: 16), color: ColorPalette.slate400,
fontSize: 16),
), ),
Text( Text(
e['subtitle'], e.subtitle!,
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
color: ColorPalette.slate800, color: ColorPalette.slate800,
@@ -98,15 +108,18 @@ class ConfirmBankAccount extends StatelessWidget {
name: 'Confirm', name: 'Confirm',
width: SizeConfig.width * .42, width: SizeConfig.width * .42,
onPressed: () { onPressed: () {
routePush(context, page: const SubmissionParent()); routePush(context,
page: const SubmissionParent());
}, },
), ),
], ],
) )
], ],
), );
}),
), ),
), ),
); );
});
} }
} }

View File

@@ -63,9 +63,13 @@ 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(
height: SizeConfig.height * .8,
child: Form(
key: provider.formKeySubmitDataBank,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const TextCaption(title: 'Input your bank account data'), const TextCaption(title: 'Input your bank account data'),
TextFormView( TextFormView(
@@ -79,11 +83,24 @@ class SubmitBankAccount extends StatelessWidget {
suffixIcon: const Icon( suffixIcon: const Icon(
Icons.keyboard_arrow_down_outlined, 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,
validator: (value) {
if (value!.isEmpty) {
return 'Field must be filled';
}
return null;
},
trailingTitleWidget: SizedBox( trailingTitleWidget: SizedBox(
width: 24, width: 24,
child: GestureDetector( child: GestureDetector(
@@ -98,6 +115,13 @@ class SubmitBankAccount extends StatelessWidget {
TextFormView( TextFormView(
name: 'Account Owner Name', name: 'Account Owner Name',
hintText: 'Input Account Name', hintText: 'Input Account Name',
ctrl: provider.ctrlNameAccountBank,
validator: (value) {
if (value!.isEmpty) {
return 'Field must be filled';
}
return null;
},
), ),
const Text( const Text(
"Make sure the account you use is in your name, not someone else's", "Make sure the account you use is in your name, not someone else's",
@@ -109,16 +133,29 @@ class SubmitBankAccount extends StatelessWidget {
ButtonView( ButtonView(
name: 'Next', name: 'Next',
onPressed: () { 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) { provider.next(context).then((value) {
if (value) { if (value) {
routePush(context, routePush(context,
page: const ConfirmBankAccount()); page: const ConfirmBankAccount(),
arguments: values);
} }
}); });
});
}
}, },
) )
], ],
), ),
),
); );
}), }),
); );

View File

@@ -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(

View File

@@ -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,21 +67,33 @@ 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',
children: [ leading: BackButtonView(
Column( onPress: () {
routePush(
context,
page: const BottomNavigationView(),
routeType: RouteType.pushReplace,
);
},
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -89,8 +102,7 @@ class _SubmissionParentState extends State<SubmissionParent> {
horizontal: 16.0, vertical: 16.0), horizontal: 16.0, vertical: 16.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children: List.generate(provider.stepAmount, (index) {
List.generate(provider.stepAmount, (index) {
return _stepItem( return _stepItem(
isCurrentStep: isCurrentStep:
provider.getCurrentStep == index + 1 || provider.getCurrentStep == index + 1 ||
@@ -100,16 +112,13 @@ class _SubmissionParentState extends State<SubmissionParent> {
), ),
), ),
Expanded( Expanded(
child: Container( child: SingleChildScrollView(
padding: padding: const EdgeInsets.symmetric(horizontal: 16.0),
const EdgeInsets.symmetric(horizontal: 16.0),
child: _content(provider.getCurrentStep), child: _content(provider.getCurrentStep),
), ),
), ),
], ],
), ),
],
),
); );
}), }),
); );

View File

@@ -176,7 +176,9 @@ 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(
key: provider.formKeySubmitIdCard,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const TextCaption( const TextCaption(
@@ -184,14 +186,35 @@ class SubmitDataIdCard extends StatelessWidget {
TextFormView( TextFormView(
name: 'NIK', name: 'NIK',
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) {
return 'Field must be filled';
}
return null;
},
),
TextFormView(
name: 'Full Name',
validator: (value) {
if (value!.isEmpty) {
return 'Field must be filled';
}
return null;
},
), ),
TextFormView(name: 'Full Name'),
DatePickerView( 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,
validatorDate: (value) {
if (value!.isEmpty) {
return 'Field must be filled';
}
return null;
},
),
photoDocument(provider), photoDocument(provider),
Container( Container(
width: SizeConfig.width, width: SizeConfig.width,
@@ -241,14 +264,19 @@ class SubmitDataIdCard extends StatelessWidget {
ButtonView( ButtonView(
name: 'Next', name: 'Next',
onPressed: () async { onPressed: () async {
if (provider.formKeySubmitIdCard.currentState!
.validate()) {
await provider.next(context).then((value) { await provider.next(context).then((value) {
if (value) { if (value) {
routePush(context, page: const SubmissionParent()); routePush(context,
page: const SubmissionParent());
} }
}); });
}
}, },
) )
], ],
),
); );
}), }),
); );

View File

@@ -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;
return Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const TextCaption(title: 'Check your e-mail'),
const ImageView(image: PathAssets.imgEmail), const ImageView(image: PathAssets.imgEmail),
Align( Align(
alignment: Alignment.center, alignment: Alignment.center,
child: RichText( child: RichText(
textAlign: TextAlign.center, textAlign: TextAlign.center,
text: TextSpan(children: [ text: TextSpan(children: [
const TextSpan( TextSpan(
text: text:
'We have sent a verification link to your e-mail. \nPlease check your email for ', 'We have sent a verification link to your e-mail. \nPlease check your email for ',
style: TextStyle( style: textTheme.displayMedium,
color: Colors.black,
decoration: TextDecoration.none,
),
), ),
TextSpan( TextSpan(
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: TapGestureRecognizer()
..onTap = () async {
await provider.next(context).then((value) {
if (value) {
routePush(context, page: const SubmissionParent());
}
});
},
text: 'verification', text: 'verification',
style: const TextStyle( style: const TextStyle(
color: Colors.blue, color: Colors.blue,
), ),
), ),
const TextSpan( TextSpan(
text: ' to \ncontinue registration.', text: ' to \ncontinue registration.',
style: TextStyle( style: textTheme.displayMedium,
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,16 +89,16 @@ 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(
height: SizeConfig.height * .78,
child: Form(
key: provider.formKeySubmitEmail,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
!provider.isEmailVerify const TextCaption(title: 'Enter your e-mail'),
? const TextCaption(title: 'Enter your e-mail') TextFormView(
: const TextCaption(title: 'Check your e-mail '),
!provider.isEmailVerify
? 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,
@@ -82,24 +111,20 @@ class SubmitEmail extends StatelessWidget {
return null; return null;
} }
}, },
// onTap: () { ),
// provider.submitEmail(); SizedBox(height: SizeConfig.height * .43),
// },
)
: _emailVerify(),
SizedBox(height: SizeConfig.height * .42),
ButtonView( ButtonView(
name: 'Next', name: 'Next',
onPressed: () async { onPressed: () async {
await provider.next(context).then((value) { if (provider.formKeySubmitEmail.currentState!
if (value) { .validate()) {
routePush(context, page: const SubmissionParent()); showEmailVerify(context, provider);
} }
});
}, },
) )
], ],
), ),
),
); );
}); });
}); });

View File

@@ -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());
} }
}); });
}
}, },
),
) )
], ],
), ),

View File

@@ -24,15 +24,18 @@ 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(
height: SizeConfig.height * .8,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const TextCaption(title: 'Draw your digital sign'), const TextCaption(title: 'Draw your digital sign'),
const ImageView(image: PathAssets.frameSignature), const ImageView(image: PathAssets.frameSignature),
const ListTileView( const ListTileView(
title: title:
'Make sure the sign you draw is match with your ID Card'), 'Make sure the sign you draw is match with your ID Card'),
SizedBox(height: SizeConfig.height * .07), SizedBox(height: SizeConfig.height * .1),
ButtonView( ButtonView(
name: 'Next', name: 'Next',
onPressed: () { onPressed: () {
@@ -44,6 +47,7 @@ class InitialSignature extends StatelessWidget {
}, },
) )
], ],
),
); );
}); });
}); });

View File

@@ -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;
}
} }

View File

@@ -50,7 +50,7 @@ class _HomeViewState extends State<HomeView> {
]; ];
StepVerification listStepVerification = StepVerification listStepVerification =
StepVerification(0, ['Registration', 'Verification', 'Complete']); StepVerification(1, ['Registration', '', 'Verification', '', 'Complete']);
List<Article> listArticle = [ List<Article> listArticle = [
Article( Article(
@@ -69,12 +69,21 @@ class _HomeViewState extends State<HomeView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: const Color(0xffF8FAFC), backgroundColor: ColorPalette.slate50,
body: SizedBox( body: CustomScrollView(
width: SizeConfig.width, slivers: [
height: SizeConfig.height, SliverAppBar(
child: Stack( onStretchTrigger: () async {
},
expandedHeight: 325,
collapsedHeight: 325,
leading: const SizedBox(),
surfaceTintColor: ColorPalette.slate50,
backgroundColor: ColorPalette.slate50,
flexibleSpace: FlexibleSpaceBar(
background: Stack(
children: [ children: [
const ImageView(image: PathAssets.imgDashboardAccount), const ImageView(image: PathAssets.imgDashboardAccount),
Column( Column(
@@ -118,11 +127,18 @@ class _HomeViewState extends State<HomeView> {
), ),
cardInvestType(), cardInvestType(),
const SizedBox( const SizedBox(
height: 32, height: 24,
), ),
Expanded( ],
child: ListView( )
padding: const EdgeInsets.all(0), ],
),
),
floating: true,
snap: true,
),
SliverToBoxAdapter(
child: Column(
children: [ children: [
cardVerification(), cardVerification(),
const SizedBox( const SizedBox(
@@ -135,12 +151,9 @@ class _HomeViewState extends State<HomeView> {
articles(), articles(),
], ],
), ),
),
],
) )
], ],
), ),
),
); );
} }
@@ -279,6 +292,7 @@ class _HomeViewState extends State<HomeView> {
child: Column( child: Column(
children: [ children: [
stepVerification(), stepVerification(),
if(listStepVerification.currentStep < 3)
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
@@ -291,6 +305,7 @@ class _HomeViewState extends State<HomeView> {
Icon( Icon(
Icons.verified, Icons.verified,
size: 18, size: 18,
color: ColorPalette.slate300,
), ),
SizedBox( SizedBox(
width: 12, width: 12,
@@ -324,6 +339,7 @@ class _HomeViewState extends State<HomeView> {
Icon( Icon(
Icons.verified, Icons.verified,
size: 18, size: 18,
color: ColorPalette.slate300,
), ),
SizedBox( SizedBox(
width: 12, width: 12,
@@ -388,11 +404,11 @@ class _HomeViewState extends State<HomeView> {
borderRadius: BorderRadius.circular(12)), borderRadius: BorderRadius.circular(12)),
child: Column( child: Column(
children: [ children: [
Text( const Text(
"Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia", "Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia",
style: TextStyle(color: ColorPalette.slate500), style: TextStyle(color: ColorPalette.slate500),
), ),
SizedBox( const SizedBox(
height: 16, height: 16,
), ),
ButtonView( ButtonView(
@@ -400,9 +416,9 @@ class _HomeViewState extends State<HomeView> {
width: SizeConfig.width, width: SizeConfig.width,
marginVertical: 0, marginVertical: 0,
heightWrapContent: true, heightWrapContent: true,
contentPadding: EdgeInsets.all(12), contentPadding: const EdgeInsets.all(12),
onPressed: () { onPressed: () {
routePush(context, page: InitialRegistrationStep()); routePush(context, page: const InitialRegistrationStep());
}, },
) )
], ],
@@ -417,57 +433,61 @@ class _HomeViewState extends State<HomeView> {
Widget stepVerification() { Widget stepVerification() {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: listStepVerification.nameStep.asMap().entries.map((e) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: List.generate(
if (e.key != 0) listStepVerification.nameStep.length,
SizedBox( (index) {
width: 30, print(index % 2);
height: 30, if (index % 2 == 0) {
child: Divider( final currentStep = index ~/ 2;
color: listStepVerification.currentStep >= e.key return Column(
? const Color(0xff2563EB)
: const Color(0xffCBD5E1),
),
),
Column(
children: [ children: [
Container( Container(
width: 30, width: 30,
height: 30, height: 30,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: listStepVerification.currentStep <= e.key color: listStepVerification.currentStep <= currentStep
? Colors.white ? Colors.white
: const Color(0xff2563EB), : const Color(0xff2563EB),
border: Border.all( border: Border.all(
color: listStepVerification.currentStep < e.key color: listStepVerification.currentStep < currentStep
? const Color(0xffCBD5E1) ? const Color(0xffCBD5E1)
: const Color(0xff2563EB), : const Color(0xff2563EB),
width: 2)), width: 2,
child: listStepVerification.currentStep <= e.key ),
),
child: listStepVerification.currentStep <= currentStep
? const SizedBox() ? const SizedBox()
: const Icon( : const Icon(
Icons.done_rounded, Icons.done_rounded,
color: Colors.white, color: Colors.white,
), ),
), ),
const SizedBox( const SizedBox(height: 8),
height: 8,
),
Text( Text(
e.value, listStepVerification.nameStep[index],
style: TextStyle( style: TextStyle(
color: listStepVerification.currentStep == e.key color: listStepVerification.currentStep == currentStep
? const Color(0xff2563EB) ? const Color(0xff2563EB)
: Colors.black), : Colors.black,
) ),
],
), ),
], ],
); );
}).toList(), } else {
return SizedBox(
width: 30,
height: 30,
child: Divider(
color: listStepVerification.currentStep > index ~/ 2
? const Color(0xff2563EB)
: const Color(0xffCBD5E1),
),
);
}
},
),
); );
} }
@@ -591,7 +611,7 @@ class _HomeViewState extends State<HomeView> {
color: ColorPalette.green100), color: ColorPalette.green100),
child: Text( child: Text(
article.type, article.type,
style: TextStyle( style: const TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: ColorPalette.green500), color: ColorPalette.green500),
), ),

View File

@@ -13,6 +13,7 @@ import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/step_subscribe/select_goal_investing.dart';
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:group_button/group_button.dart'; import 'package:group_button/group_button.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -79,6 +80,8 @@ class _ProductViewState extends State<ProductView> {
}); });
} }
double currentScroll = 0;
@override @override
void initState() { void initState() {
machineController.text = NumberFormatter.numberCurrency(100000, 'Rp ', 'id_ID', decimalDigits: 0); machineController.text = NumberFormatter.numberCurrency(100000, 'Rp ', 'id_ID', decimalDigits: 0);
@@ -104,21 +107,45 @@ class _ProductViewState extends State<ProductView> {
return ChangeNotifierProvider( return ChangeNotifierProvider(
create: (context) => ProductViewModel(), create: (context) => ProductViewModel(),
child: Scaffold( child: Scaffold(
body: SizedBox( body: NotificationListener<ScrollNotification>(
child: Stack( onNotification: (notification) {
children: [ setState(() {
const ImageView(image: PathAssets.imgDashboardAccount), currentScroll = notification.metrics.pixels;
Column( });
children: [ return false;
const SizedBox( },
height: 50, child: CustomScrollView(
slivers: [
SliverAppBar(
toolbarHeight: 70,
expandedHeight: 170,
leadingWidth: 0,
floating: false,
automaticallyImplyLeading: false,
title: AnimatedCrossFade(
firstChild: Text(
widget.selectedProduct.name ?? '',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 18
), ),
const Padding( ),
padding: EdgeInsets.symmetric(horizontal: 24), secondChild: Padding(
child: Row( padding: const EdgeInsets.only(left: 8),
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: BackButtonView(),
children: [ ),
BackButtonView(), crossFadeState: currentScroll >= 85 ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(milliseconds: 200)
),
centerTitle: false,
snap: false,
pinned: true,
backgroundColor: Color(0xFF1745C8).withOpacity(currentScroll >= 95 ? 1 : currentScroll / 95),
surfaceTintColor: ColorPalette.primary,
actions: [
Wrap( Wrap(
spacing: 12, spacing: 12,
children: [ children: [
@@ -126,25 +153,43 @@ class _ProductViewState extends State<ProductView> {
Icon(Icons.file_download_outlined, color: ColorPalette.blue200, size: 32), Icon(Icons.file_download_outlined, color: ColorPalette.blue200, size: 32),
Icon(Icons.star_outline_rounded, color: ColorPalette.blue200, size: 32) Icon(Icons.star_outline_rounded, color: ColorPalette.blue200, size: 32)
], ],
) ),
SizedBox(width: 24,)
], ],
), flexibleSpace: Opacity(
), opacity: currentScroll > 0 ? ((95 - currentScroll) / 95) > 0.01 ? ((95 - currentScroll) / 95) : 0 : 1,
const SizedBox( child: Stack(
height: 24, children: [
), ImageView(image: PathAssets.imgDashboardAccount, width: SizeConfig.width, height: 200),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
headContainer(), headContainer(),
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
Expanded( Container(
child: contentContainer() height: 12,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12)
)
),
) )
], ],
) )
], ],
), ),
), ),
),
SliverToBoxAdapter(
child: contentContainer(),
)
],
),
),
bottomNavigationBar: !widget.seeMore ? bottomNavigationBar: !widget.seeMore ?
Container( Container(
height: SizeConfig.height * .1, height: SizeConfig.height * .1,
@@ -220,8 +265,11 @@ class _ProductViewState extends State<ProductView> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
), ),
child: ListView( child: Column(
children: [ children: [
const SizedBox(
height: 12,
),
ProductChartView( ProductChartView(
tabType: listTab[selectedTab], tabType: listTab[selectedTab],
lastTime: selectedTime.completeName, lastTime: selectedTime.completeName,

View File

@@ -0,0 +1,35 @@
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CancelView extends StatelessWidget {
const CancelView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Consumer<TransactionViewModel>(
builder: (context, provider, child) => Column(
children: [
if (provider.listOnProcessTransaction.isEmpty)
EmptyCardTransaction(
onPressedButton: () {},
),
...provider.listOnProcessTransaction.map((e) {
return CardTransactionView(
step: 'cancel',
type: 'type',
amount: 'amount',
iconPath: 'iconPath',
subs: 'subs',
onTap: () {},
);
}),
],
),
),
);
}
}

View File

@@ -0,0 +1,37 @@
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class DoneView extends StatelessWidget {
const DoneView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Consumer<TransactionViewModel>(
builder: (context, provider, child) {
return Column(
children: [
if (provider.listOnProcessTransaction.isEmpty)
EmptyCardTransaction(
onPressedButton: () {},
),
...provider.listOnProcessTransaction.map((e) {
return CardTransactionView(
step: 'done',
type: 'type',
amount: 'amount',
iconPath: 'iconPath',
subs: 'subs',
onTap: () {},
);
}),
],
);
},
),
);
}
}

View File

@@ -0,0 +1,34 @@
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class OnProcessView extends StatelessWidget {
const OnProcessView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child:
Consumer<TransactionViewModel>(builder: (context, provider, child) {
return Column(children: [
if (provider.listOnProcessTransaction.isEmpty)
EmptyCardTransaction(
onPressedButton: () {},
),
...provider.listOnProcessTransaction.map((e) {
return CardTransactionView(
step: 'on process',
type: 'type',
amount: 'amount',
iconPath: 'iconPath',
subs: 'subs',
onTap: () {},
);
}),
]);
}),
);
}
}

View File

@@ -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) {
List<Tab> textTabs = const [
Tab(text: 'Waiting'),
Tab(text: 'On process'),
Tab(text: 'Done'),
Tab(text: 'Cancel'),
];
List<Widget> listTabBarView = const [
WaitingView(),
OnProcessView(),
DoneView(),
CancelView(),
];
return ChangeNotifierProvider(
create: (context) => TransactionViewModel(),
builder: (context, child) {
return Scaffold( return Scaffold(
appBar: CustomAppBar(height: SizeConfig.height * 0.08, title: 'Transaction'), backgroundColor: ColorPalette.primary,
body: SizedBox(
child: Stack(
children: [
const ImageView(image: PathAssets.imgDashboardAccount),
Column(
children: [
SizedBox(
height: SizeConfig.height * .05,
),
const Center(
child: Text(
'Transaction',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: Colors.white),
),
),
SizedBox(
height: SizeConfig.height * .04,
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 24),
child: FlutterToggleTab(
height: SizeConfig.height * .065,
width: SizeConfig.width * .2,
marginSelected: const EdgeInsets.all(8.0),
isScroll: false,
selectedTextStyle: const TextStyle(
color: ColorPalette.primary,
fontWeight: FontWeight.w700,
),
unSelectedTextStyle: const TextStyle(
color: ColorPalette.blackFont,
fontWeight: FontWeight.w700,
),
unSelectedBackgroundColors: const [
ColorPalette.blue50
],
selectedBackgroundColors: const [ColorPalette.white],
labels: const ['Subscribe', 'Reedem'],
selectedLabelIndex: (p0) {},
selectedIndex: 0,
),
),
Expanded(
child: DefaultTabController(
length: textTabs.length,
child: Container(
color: Colors.transparent,
padding: const EdgeInsets.only(top: 32.0),
child: Container(
margin: const EdgeInsets.only(top: 24),
padding: const EdgeInsets.only(top: 16.0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24)),
),
child: Column(
children: [
TabBar(
tabs: textTabs,
indicatorColor: Colors.blueAccent,
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 4.0,
),
child: TabBarView(children: listTabBarView),
))
],
),
),
),
)),
],
)
],
),
),
); );
});
} }
} }

View File

@@ -0,0 +1,42 @@
import 'package:cims_apps/application/assets/path_assets.dart';
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
import 'package:cims_apps/core/utils/number_formatter.dart';
import 'package:cims_apps/core/utils/string_utils.dart';
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class WaitingView extends StatelessWidget {
const WaitingView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child:
Consumer<TransactionViewModel>(builder: (context, provider, child) {
return Column(
children: [
provider.listWaitingTransaction.isNotEmpty
? CardTransactionView(
onTap: () {},
iconPath: PathAssets.iconEducation,
type: 'Education',
amount: NumberFormatter.numberCurrency(
6000000,
'Rp ',
'id_ID',
decimalDigits: 0,
),
timeTransaction: StringUtils.formatTime(DateTime.now()),
subs: '3 Subscription',
step: 'waiting')
: EmptyCardTransaction(
onPressedButton: () {},
),
],
);
}),
);
}
}

View File

@@ -0,0 +1,8 @@
import 'package:flutter/material.dart';
class TransactionViewModel extends ChangeNotifier {
List listWaitingTransaction = [1];
List listOnProcessTransaction = [];
List listDoneTransaction = [];
List listCancelTransaction = [];
}

View File

@@ -76,10 +76,8 @@ class MyApp extends StatelessWidget {
secondary: const Color(0xFFFECDA6), secondary: const Color(0xFFFECDA6),
onBackground: const Color(0xFFA9A9A9), onBackground: const Color(0xFFA9A9A9),
), ),
bottomSheetTheme: BottomSheetThemeData( bottomSheetTheme: const BottomSheetThemeData(
backgroundColor: Colors.white, backgroundColor: Colors.white, surfaceTintColor: Colors.white)
surfaceTintColor: Colors.white
)
// useMaterial3: true, // useMaterial3: true,
), ),
initialRoute: initialRoute, initialRoute: initialRoute,

View File

@@ -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

View File

@@ -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