diff --git a/android/app/build.gradle b/android/app/build.gradle index c2d4e08..0530d98 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -12,6 +12,12 @@ if (localPropertiesFile.exists()) { } } +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -51,11 +57,21 @@ android { versionName flutterVersionName } + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + // signingConfig signingConfigs.debug + signingConfig signingConfigs.release } } } diff --git a/assets/icons/icon-balance.png b/assets/icons/icon-balance.png new file mode 100644 index 0000000..fea0f54 Binary files /dev/null and b/assets/icons/icon-balance.png differ diff --git a/assets/icons/icon-coins.png b/assets/icons/icon-coins.png new file mode 100644 index 0000000..7eee7fc Binary files /dev/null and b/assets/icons/icon-coins.png differ diff --git a/assets/icons/icon-money-receive.png b/assets/icons/icon-money-receive.png new file mode 100644 index 0000000..7f8f94f Binary files /dev/null and b/assets/icons/icon-money-receive.png differ diff --git a/assets/icons/icon-strongbox.png b/assets/icons/icon-strongbox.png new file mode 100644 index 0000000..d7e94bc Binary files /dev/null and b/assets/icons/icon-strongbox.png differ diff --git a/assets/images/img-business-failure.png b/assets/images/img-business-failure.png new file mode 100644 index 0000000..9aa4de9 Binary files /dev/null and b/assets/images/img-business-failure.png differ diff --git a/assets/images/img-cat.png b/assets/images/img-cat.png new file mode 100644 index 0000000..3d02a68 Binary files /dev/null and b/assets/images/img-cat.png differ diff --git a/assets/images/img-data-analysis.png b/assets/images/img-data-analysis.png new file mode 100644 index 0000000..26c8473 Binary files /dev/null and b/assets/images/img-data-analysis.png differ diff --git a/assets/images/img-data-report.png b/assets/images/img-data-report.png new file mode 100644 index 0000000..0b07fa5 Binary files /dev/null and b/assets/images/img-data-report.png differ diff --git a/assets/images/img-deer.png b/assets/images/img-deer.png new file mode 100644 index 0000000..aceaae3 Binary files /dev/null and b/assets/images/img-deer.png differ diff --git a/assets/images/img-growing.png b/assets/images/img-growing.png new file mode 100644 index 0000000..3b4c28d Binary files /dev/null and b/assets/images/img-growing.png differ diff --git a/assets/images/img-leader.png b/assets/images/img-leader.png new file mode 100644 index 0000000..4697310 Binary files /dev/null and b/assets/images/img-leader.png differ diff --git a/assets/images/img-lion.png b/assets/images/img-lion.png new file mode 100644 index 0000000..8077b80 Binary files /dev/null and b/assets/images/img-lion.png differ diff --git a/assets/images/img-money-income.png b/assets/images/img-money-income.png new file mode 100644 index 0000000..df194c1 Binary files /dev/null and b/assets/images/img-money-income.png differ diff --git a/lib/application/assets/path_assets.dart b/lib/application/assets/path_assets.dart index 22f6b7d..ed0d088 100644 --- a/lib/application/assets/path_assets.dart +++ b/lib/application/assets/path_assets.dart @@ -10,14 +10,10 @@ class PathAssets { static const String iconGoogle = 'assets/icons/icon-google.png'; static const String icon1 = 'assets/icons/icon-1.png'; static const String iconConnect = 'assets/icons/icon-connect.png'; - static const String iconPortofolioBonds = - 'assets/icons/icon-portofolio-bonds.png'; - static const String iconPortofolioShares = - 'assets/icons/icon-portofolio-shares.png'; - static const String iconPortofolioSharia = - 'assets/icons/icon-portofolio-sharia.png'; - static const String iconPortofolioMoneyMarket = - 'assets/icons/icon-portofolio-moneymarket.png'; + static const String iconPortofolioBonds = 'assets/icons/icon-portofolio-bonds.png'; + static const String iconPortofolioShares = 'assets/icons/icon-portofolio-shares.png'; + static const String iconPortofolioSharia = 'assets/icons/icon-portofolio-sharia.png'; + static const String iconPortofolioMoneyMarket = 'assets/icons/icon-portofolio-moneymarket.png'; static const String iconShield = 'assets/icons/icon-shield.png'; static const String iconFlag = 'assets/icons/icon-flag.png'; static const String iconKtp1 = 'assets/icons/icon-ktp1.png'; @@ -28,6 +24,10 @@ class PathAssets { static const String iconSelfie2 = 'assets/icons/icon-selfie2.png'; static const String iconSelfie3 = 'assets/icons/icon-selfie3.png'; static const String iconSelfie4 = 'assets/icons/icon-selfie4.png'; + static const String iconStrongBox = 'assets/icons/icon-strongbox.png'; + static const String iconBalance = 'assets/icons/icon-balance.png'; + static const String iconMoneyReceive = 'assets/icons/icon-money-receive.png'; + static const String iconCoins = 'assets/icons/icon-coins.png'; /// IMAGE static const String imgSplashLogo = 'assets/images/splash-logo.png'; @@ -40,12 +40,20 @@ class PathAssets { static const String imgKtpCropped = 'assets/images/img-ktp-cropped.png'; static const String imgKtpClear = 'assets/images/img-ktp-clear.png'; static const String imgKtpBlur = 'assets/images/img-ktp-blur.png'; - static const String imgDashboardAccount = - 'assets/images/img-dashboard-account.png'; + static const String imgDashboardAccount = 'assets/images/img-dashboard-account.png'; static const String imgCarousel = 'assets/images/img-carousel.png'; static const String imgArticles = 'assets/images/img-articles.png'; static const String imgProduct = 'assets/images/img-product.png'; static const String imgSuccessSignup = 'assets/images/img-success-signup.png'; static const String imgBgKtp = 'assets/images/img-bg-photo-ktp.png'; static const String imgBgSelfie = 'assets/images/img-bg-photo-selfie.png'; + static const String imgDataReport = 'assets/images/img-data-report.png'; + static const String imgDataAnalysis = 'assets/images/img-data-analysis.png'; + static const String imgBusinessFailure = 'assets/images/img-business-failure.png'; + static const String imgLeader = 'assets/images/img-leader.png'; + static const String imgMoneyIncome = 'assets/images/img-money-income.png'; + static const String imgGrowing = 'assets/images/img-growing.png'; + static const String imgCat = 'assets/images/img-cat.png'; + static const String imgDeer = 'assets/images/img-deer.png'; + static const String imgLion = 'assets/images/img-lion.png'; } diff --git a/lib/application/component/button/button_back.dart b/lib/application/component/button/button_back.dart index 091b8bb..37e1a51 100644 --- a/lib/application/component/button/button_back.dart +++ b/lib/application/component/button/button_back.dart @@ -1,21 +1,25 @@ +import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/utils/size_config.dart'; import 'package:flutter/material.dart'; class ButtonBack extends StatelessWidget { - const ButtonBack({super.key}); + final EdgeInsets? margin; + final void Function()? onPress; + const ButtonBack({super.key, this.margin, this.onPress}); @override Widget build(BuildContext context) { - return SizedBox( + return Container( + margin: margin ?? EdgeInsets.all(0), width: SizeConfig.width * 0.1, child: IconButton( style: IconButton.styleFrom( backgroundColor: Colors.white, - shape: const CircleBorder() + shape: const CircleBorder( + side: BorderSide(color: ColorPalette.slate200) + ) ), - onPressed: () { - Navigator.pop(context); - }, + onPressed: onPress ?? () => Navigator.pop(context), icon: const Icon(Icons.arrow_back) ), ); diff --git a/lib/application/component/text_form/text_form_view.dart b/lib/application/component/text_form/text_form_view.dart index 96668ba..4da4e2e 100644 --- a/lib/application/component/text_form/text_form_view.dart +++ b/lib/application/component/text_form/text_form_view.dart @@ -33,6 +33,7 @@ class TextFormView extends StatelessWidget { final Color? disabledborderColor; final bool? enableInteractiveSelection; final Color? fontColorDisabled; + final EdgeInsets? contentPadding; final FocusNode? focusNode; // ignore: prefer_const_constructors_in_immutables @@ -189,10 +190,11 @@ class TextFormView extends StatelessWidget { suffixIconConstraints: suffixIconConstraints, prefixIconConstraints: preffixIconConstraints, prefix: prefix, - contentPadding: const EdgeInsets.symmetric( + contentPadding: contentPadding ?? const EdgeInsets.symmetric( horizontal: 8.0, vertical: 16.0, - )), + ) + ), ) ], ); diff --git a/lib/application/theme/color_palette.dart b/lib/application/theme/color_palette.dart index 6e37bd2..22711ea 100644 --- a/lib/application/theme/color_palette.dart +++ b/lib/application/theme/color_palette.dart @@ -73,13 +73,13 @@ class ColorPalette { static const Color chathamsBlue = Color(0xFF285BB9); static const Color background = Color(0xFFDADADA); static const Color backgroundBlueLight = Color(0xFFEBF3FD); - static const Color slate500 = Color(0xFF64748B); static const Color blue50 = Color(0xFFEFF6FF); static const Color blue200 = Color(0xFFBFDBFE); static const Color slate50 = Color(0xFFF8FAFC); static const Color slate200 = Color(0xFFE2E8F0); static const Color slate300 = Color(0xFFCBD5E1); static const Color slate400 = Color(0xFF94A3B8); + static const Color slate500 = Color(0xFF64748B); static const Color slate800 = Color(0xFF1E293B); static const Color purple100 = Color(0xFFEDE9FE); static const Color purple500 = Color(0xFF8B5CF6); diff --git a/lib/features/auth/login/view/login_view.dart b/lib/features/auth/login/view/login_view.dart new file mode 100644 index 0000000..35157ca --- /dev/null +++ b/lib/features/auth/login/view/login_view.dart @@ -0,0 +1,96 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_back.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/login/view/password_view.dart'; +import 'package:cims_apps/features/auth/login/view/phone_number_view.dart'; +import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/risk_profile_view.dart'; +import 'package:cims_apps/features/bottom_navigation_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; + +class LoginView extends StatefulWidget { + const LoginView({super.key}); + + @override + State createState() => _LoginViewState(); +} + +class _LoginViewState extends State { + int currentPage = 0; + PageController pageController = PageController(initialPage: 0); + TextEditingController phoneNumberController = TextEditingController(); + TextEditingController passwordController = TextEditingController(); + + @override + void dispose() { + // TODO: implement dispose + pageController.dispose(); + phoneNumberController.dispose(); + passwordController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => LoginViewModel(), + child: WillPopScope( + onWillPop: () async { + if(currentPage == 1){ + currentPage--; + pageController.jumpToPage(0); + return false; + } + return true; + }, + child: Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + toolbarHeight: 70, + backgroundColor: Colors.white, + surfaceTintColor: Colors.white, + automaticallyImplyLeading: false, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ButtonBack(), + const Text('Sign In'), + SizedBox( + width: SizeConfig.width * 0.1, + ) + ], + ), + shape: const RoundedRectangleBorder( + side: BorderSide(color: ColorPalette.slate200) + ), + ), + body: PageView( + physics: NeverScrollableScrollPhysics(), + controller: pageController, + children: [ + PhoneNumberView(nextStep: nextStep, controller: phoneNumberController), + PasswordView(nextStep: nextStep, controller: passwordController) + ], + ), + ), + ), + ); + } + + void nextStep() { + if(pageController.page == 0){ + currentPage++; + pageController.jumpToPage(1); + }else{ + routePush(context, page: RiskProfileView()); + } + } +} diff --git a/lib/features/auth/login/view/password_view.dart b/lib/features/auth/login/view/password_view.dart new file mode 100644 index 0000000..a5ea828 --- /dev/null +++ b/lib/features/auth/login/view/password_view.dart @@ -0,0 +1,78 @@ +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PasswordView extends StatelessWidget { + final void Function() nextStep; + final TextEditingController controller; + const PasswordView({super.key, required this.nextStep, required this.controller}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, provider, child) { + return Container( + width: SizeConfig.width, + height: SizeConfig.height, + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextTitle(title: 'Enter your password', fontSize: 24), + SizedBox( + height: 24, + ), + TextFormView( + name: 'Password', + ctrl: controller, + obscureText: !provider.showPassword, + contentPadding: EdgeInsets.all(12), + suffixIcon: GestureDetector( + onTap: () { + provider.changeShowPassword(); + }, + child: Icon( + provider.showPassword + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + color: ColorPalette.greyDarker, + ), + ), + ), + TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.all(0) + ), + onPressed: () { + + }, + child: Text( + 'Forget the password?', + style: TextStyle( + color: ColorPalette.primary, + ), + ) + ), + SizedBox( + height: 16, + ), + ButtonView( + name: 'Confirm', + heightWrapContent: true, + width: SizeConfig.width, + marginVertical: 0, + contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), + onPressed: nextStep, + ) + ], + ), + ); + } + ); + } +} diff --git a/lib/features/auth/login/view/phone_number_view.dart b/lib/features/auth/login/view/phone_number_view.dart new file mode 100644 index 0000000..c4c2ffb --- /dev/null +++ b/lib/features/auth/login/view/phone_number_view.dart @@ -0,0 +1,116 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/registration_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class PhoneNumberView extends StatelessWidget { + final void Function() nextStep; + final TextEditingController controller; + const PhoneNumberView({super.key, required this.nextStep, required this.controller}); + + @override + Widget build(BuildContext context) { + return Container( + width: SizeConfig.width, + height: SizeConfig.height, + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextTitle(title: 'Enter your phone number', fontSize: 24), + SizedBox( + height: 24, + ), + TextFormView( + name: 'Phone Number', + keyboardType: TextInputType.number, + ctrl: controller, + inputFormatters: [ + FilteringTextInputFormatter.deny(RegExp(r'^0')) + ], + prefixIcon: Container( + width: SizeConfig.width * .23, + padding: + const EdgeInsets.symmetric(horizontal: 16.0), + margin: const EdgeInsets.only(right: 16), + decoration: const BoxDecoration( + color: ColorPalette.grey, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + bottomLeft: Radius.circular(8), + )), + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ImageView( + image: PathAssets.iconFlag, + fit: BoxFit.contain, + width: 24, + height: 24, + ), + Text( + '+62', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.slate800, + ), + ) + ], + )), + validator: (value) { + if (value!.isEmpty) { + return 'Phone number must be filled'; + } else { + return null; + } + }, + ), + SizedBox( + height: 32, + ), + ButtonView( + name: 'Next', + heightWrapContent: true, + width: SizeConfig.width, + marginVertical: 0, + contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), + onPressed: nextStep, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Don't have an account yet?", + style: TextStyle( + color: ColorPalette.slate500, + ), + ), + TextButton( + onPressed: () { + routePush(context, page: RegistrationView()); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.all(0) + ), + child: Text( + 'Sign Up', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.primary + ), + ) + ) + ], + ) + ], + ), + ); + } +} diff --git a/lib/features/auth/login/view_model/login_view_model.dart b/lib/features/auth/login/view_model/login_view_model.dart new file mode 100644 index 0000000..df7a02d --- /dev/null +++ b/lib/features/auth/login/view_model/login_view_model.dart @@ -0,0 +1,10 @@ +import 'package:flutter/foundation.dart'; + +class LoginViewModel extends ChangeNotifier { + bool showPassword = false; + + void changeShowPassword() { + showPassword = !showPassword; + notifyListeners(); + } +} \ No newline at end of file diff --git a/lib/features/auth/registration/view/risk_profile/question_view.dart b/lib/features/auth/registration/view/risk_profile/question_view.dart new file mode 100644 index 0000000..c758c80 --- /dev/null +++ b/lib/features/auth/registration/view/risk_profile/question_view.dart @@ -0,0 +1,164 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_back.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/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/results_view.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/risk_profile_view.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/risk_profile_view_model/risk_profile_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class QuestionView extends StatefulWidget { + const QuestionView({super.key}); + + @override + State createState() => _QuestionViewState(); +} + +class _QuestionViewState extends State { + int currentPage = 0; + PageController pageController = PageController(); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => RiskProfileViewModel(), + child: Consumer( + builder: (context, provider, child) { + return Scaffold( + appBar: AppBar( + toolbarHeight: 70, + backgroundColor: Colors.white, + surfaceTintColor: Colors.white, + automaticallyImplyLeading: false, + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ButtonBack(), + const Text('Risk Profile', textAlign: TextAlign.center), + SizedBox( + width: SizeConfig.width * 0.1 + ) + ], + ), + shape: const RoundedRectangleBorder( + side: BorderSide(color: ColorPalette.slate200) + ), + ), + body: PageView( + controller: pageController, + physics: NeverScrollableScrollPhysics(), + children: provider.listRiskProfileQuestion.asMap().entries.map((e) { + return containerQuestion( + e.value, + e.key, + (index, score) => provider.selectedAnswer(index, score) + ); + }).toList(), + ), + bottomNavigationBar: SizedBox( + height: 84, + child: ButtonView( + name: 'Next', + marginVertical: 16, + onPressed: () { + if(currentPage > 3){ + int totalScore = provider.listScore.reduce((value, element) => value + element); + provider.setTypeResult(totalScore); + routePush(context, page: ResultsView(totalScore: totalScore.toString(), typeResult: provider.typeResult)); + }else{ + setState(() { + currentPage += 1; + }); + pageController.nextPage(duration: Duration(milliseconds: 300), curve: Curves.ease); + } + }, + ), + ), + ); + } + ), + ); + } + + Widget containerQuestion(RiskProfileQuestion data, int index, void Function(int index, int score) onTapAnswers) { + return SizedBox( + height: SizeConfig.height, + width: SizeConfig.width, + child: ListView( + padding: EdgeInsets.all(24), + children: [ + ImageView( + image: data.img, + fit: BoxFit.fitWidth, + ), + SizedBox( + height: 16, + ), + Text( + '${index + 1} of 5 question', + style: TextStyle( + fontWeight: FontWeight.bold, + color: ColorPalette.primary + ), + ), + SizedBox( + height: 12, + ), + Text( + data.question, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + color: ColorPalette.slate800 + ), + ), + SizedBox( + height: 16, + ), + Column( + children: data.answers.asMap().entries.map((e) { + bool selected = data.selectedScore == e.value.score; + return GestureDetector( + onTap: () { + onTapAnswers(index, e.value.score); + }, + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + margin: EdgeInsets.only(top: 12), + padding: EdgeInsets.all(12), + decoration: BoxDecoration( + border: Border.all(color: selected ? ColorPalette.primary : ColorPalette.slate200), + borderRadius: BorderRadius.circular(8) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + e.value.title, + style: TextStyle( + fontSize: 16, + color: selected ? ColorPalette.primary : ColorPalette.slate500, + fontWeight: FontWeight.w500 + ), + ), + ), + if(selected)...[ + Icon(Icons.check_circle_rounded, color: ColorPalette.primary) + ] + ], + ), + ), + ); + }).toList(), + ) + ], + ), + ); + } +} diff --git a/lib/features/auth/registration/view/risk_profile/results_view.dart b/lib/features/auth/registration/view/risk_profile/results_view.dart new file mode 100644 index 0000000..6faac0f --- /dev/null +++ b/lib/features/auth/registration/view/risk_profile/results_view.dart @@ -0,0 +1,187 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_back.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/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/registration_password_view.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/risk_profile_view_model/risk_profile_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ResultsView extends StatelessWidget { + final String totalScore; + final RiskProfileResult typeResult; + const ResultsView({super.key, required this.typeResult, required this.totalScore}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + toolbarHeight: 70, + backgroundColor: Colors.white, + surfaceTintColor: Colors.white, + automaticallyImplyLeading: false, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ButtonBack(), + const Text('Risk Profile', textAlign: TextAlign.center), + SizedBox( + width: SizeConfig.width * 0.1 + ) + ], + ), + shape: const RoundedRectangleBorder( + side: BorderSide(color: ColorPalette.slate200) + ), + ), + body: SingleChildScrollView( + padding: EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Container( + decoration: BoxDecoration( + color: typeResult.color, + image: DecorationImage(image: AssetImage(typeResult.img), alignment: Alignment.centerRight) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + typeResult.type, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + color: ColorPalette.white + ), + ), + SizedBox(height: 16,), + Text('Total Score :', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: ColorPalette.white + ), + ), + Text(totalScore, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 28, + color: ColorPalette.white + ), + ) + ], + ), + ), + ], + ), + ), + ), + SizedBox( + height: 24, + ), + Text( + typeResult.desc, + style: TextStyle( + color: ColorPalette.slate500, + fontSize: 16 + ) + ), + SizedBox( + height: 24, + ), + Text( + 'Suitable Product', + style: TextStyle( + color: ColorPalette.slate800, + fontWeight: FontWeight.bold, + fontSize: 16 + ), + ), + SizedBox( + height: 16, + ), + Wrap( + runSpacing: 16, + children: typeResult.suitableProduct.map((e) { + return Container( + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + border: Border.all(color: ColorPalette.slate200), + ), + child: Row( + children: [ + Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: typeResult.color.withOpacity(0.1) + ), + child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: typeResult.color) + ), + SizedBox( + width: 12, + ), + Expanded( + child: Text(e['desc'], + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: ColorPalette.slate800 + ), + ), + ) + ], + ), + ); + }).toList(), + ), + SizedBox( + height: 32, + ), + ButtonView( + name: 'Re-test', + onPressed: () { + }, + marginVertical: 0, + backgroundColor: ColorPalette.white, + textColor: ColorPalette.primary, + borderColor: ColorPalette.primary, + isOutlined: true, + textSize: 16, + heightWrapContent: true, + contentPadding: EdgeInsets.all(16), + width: SizeConfig.width, + ), + SizedBox( + height: 16, + ), + ButtonView( + name: 'Confirm', + onPressed: () { + routePush(context, page: DialogSuccess()); + }, + marginVertical: 0, + textSize: 16, + heightWrapContent: true, + contentPadding: EdgeInsets.all(16), + width: SizeConfig.width, + ) + ], + ), + ), + ); + } +} diff --git a/lib/features/auth/registration/view/risk_profile/risk_profile_view.dart b/lib/features/auth/registration/view/risk_profile/risk_profile_view.dart new file mode 100644 index 0000000..c274599 --- /dev/null +++ b/lib/features/auth/registration/view/risk_profile/risk_profile_view.dart @@ -0,0 +1,112 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_back.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/theme/color_palette.dart'; +import 'package:cims_apps/core/route/route.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/risk_profile/question_view.dart'; +import 'package:flutter/material.dart'; + +class RiskProfileView extends StatelessWidget { + const RiskProfileView({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + toolbarHeight: 70, + backgroundColor: Colors.white, + surfaceTintColor: Colors.white, + automaticallyImplyLeading: false, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ButtonBack(), + const Text('Risk Profile', textAlign: TextAlign.center), + SizedBox( + width: SizeConfig.width * 0.1 + ) + ], + ), + shape: const RoundedRectangleBorder( + side: BorderSide(color: ColorPalette.slate200) + ), + ), + body: Container( + width: SizeConfig.width, + height: SizeConfig.height, + padding: EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + ImageView(image: PathAssets.imgDataReport), + SizedBox( + height: 24, + ), + Text( + 'Know Your Risk Profile', + textAlign: TextAlign.center, + style: TextStyle( + color: ColorPalette.slate800, + fontWeight: FontWeight.bold, + fontSize: 24 + ), + ), + SizedBox( + height: 12, + ), + Text( + 'We will provide recommendations that match your profile and risk tolerance level.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate500 + ), + ), + ], + ), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ImageView( + image: PathAssets.iconShield, + width: 20, + height: 22, + ), + SizedBox( + width: 8, + ), + Text( + 'Your data is secure and encrypted', + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.primary, + fontSize: 16 + ), + ) + ], + ), + SizedBox( + height: 24, + ), + ButtonView( + name: "Let's Start", + onPressed: () { + routePush(context, page: QuestionView()); + }, + marginVertical: 0, + ) + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/features/auth/registration/view/risk_profile/risk_profile_view_model/risk_profile_view_model.dart b/lib/features/auth/registration/view/risk_profile/risk_profile_view_model/risk_profile_view_model.dart new file mode 100644 index 0000000..929b5cb --- /dev/null +++ b/lib/features/auth/registration/view/risk_profile/risk_profile_view_model/risk_profile_view_model.dart @@ -0,0 +1,133 @@ + +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:flutter/material.dart'; + +class RiskProfileQuestion { + String img; + int selectedScore; + String question; + List answers; + + RiskProfileQuestion(this.img, this.question, this.selectedScore, this.answers); +} + +class RiskProfileResult { + String type; + String img; + String desc; + Color color; + List suitableProduct; + + RiskProfileResult(this.type, this.img, this.color, this.desc, this.suitableProduct); +} + +class Answer { + int score; + String title; + + Answer(this.score, this.title); +} + +class RiskProfileViewModel extends ChangeNotifier { + List listScore = [0,0,0,0,0]; + RiskProfileResult typeResult = RiskProfileResult('', '', Colors.transparent, '', []); + + List listRiskProfileQuestion = [ + RiskProfileQuestion( + PathAssets.imgGrowing, 'How long is your planned investment horizon?', 0, + [ + Answer(2, '<1 year'), + Answer(4, '1-3 year'), + Answer(6, '3-5 year'), + Answer(8, '>5 year') + ] + ), + RiskProfileQuestion( + PathAssets.imgLeader, 'Investment objectives of mutualfund investors?', 0, + [ + Answer(2, 'Security of Investment Funds'), + Answer(4, 'Investment Income and Security'), + Answer(6, 'Revenue and growth over the long term'), + Answer(8, 'Growth') + ] + ), + RiskProfileQuestion( + PathAssets.imgBusinessFailure, 'How much can I afford to lose on my investment (Risk level you can afford)?', 0, + [ + Answer(2, '0%'), + Answer(4, '<25%'), + Answer(6, '26-50%'), + Answer(8, '>50%') + ] + ), + RiskProfileQuestion( + PathAssets.imgMoneyIncome, 'I am willing to use .... % of my income for investment (financial circumstances of the financier)?', 0, + [ + Answer(2, '0%'), + Answer(4, '<25%'), + Answer(6, '26-50%'), + Answer(8, '>50%') + ] + ), + RiskProfileQuestion( + PathAssets.imgDataAnalysis, 'Mutual Fund Investment Knowledge Level?', 0, + [ + Answer(2, 'Low'), + Answer(4, 'Medium'), + Answer(6, 'High'), + ] + ) + ]; + + List listRiskProfileResult = [ + RiskProfileResult( + 'Conservative', + PathAssets.imgCat, + ColorPalette.green500, + 'Investors with a conservative risk profile are risk-averse or do not want to experience large losses. Therefore, mutual fund products that are suitable for conservative investors are products that have low risk and stable returns.', + [ + {'desc': 'Money Market Mutual Fund', 'icon': PathAssets.iconStrongBox}, + {'desc': 'Fixed Income Mutual Fund', 'icon': PathAssets.iconMoneyReceive}, + {'desc': 'Balanced Mutual Fund', 'icon': PathAssets.iconBalance}, + ] + ), + RiskProfileResult( + 'Moderate', + PathAssets.imgDeer, + ColorPalette.orange500, + 'Investors with a moderate risk profile are investors who are ready to accept moderate risk to get higher returns than conservative mutual fund products. Therefore, mutual fund products that are suitable for moderate investors are products that have moderate risk and higher returns than conservative mutual fund products.', + [ + {'desc': 'Fixed Income Mutual Fund', 'icon': PathAssets.iconMoneyReceive}, + {'desc': 'Balanced Mutual Fund', 'icon': PathAssets.iconBalance}, + ] + ), + RiskProfileResult( + 'Aggressive', + PathAssets.imgLion, + ColorPalette.purple500, + 'Investors with an aggressive risk profile are investors who are ready to accept high risks to get high returns. Therefore, mutual fund products that are suitable for aggressive investors are products that have high risk and high returns.', + [ + {'desc': 'Equity Mutual Fund', 'icon': PathAssets.iconCoins}, + {'desc': 'Aggressive Balanced Fund', 'icon': PathAssets.iconBalance}, + ] + ) + ]; + + void selectedAnswer(int index, int score) { + listScore[index] = score; + listRiskProfileQuestion[index].selectedScore = score; + notifyListeners(); + } + + void setTypeResult(int totalScore) { + if(totalScore <= 25){ + typeResult = listRiskProfileResult[0]; + }else if(totalScore <= 50){ + typeResult = listRiskProfileResult[1]; + }else{ + typeResult = listRiskProfileResult[2]; + } + notifyListeners(); + } +} \ No newline at end of file diff --git a/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart b/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart index 8b35382..0e81a6d 100644 --- a/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart +++ b/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart @@ -1,10 +1,13 @@ import 'package:carousel_slider/carousel_slider.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/image/image_view.dart'; import 'package:cims_apps/application/component/text_title/text_title.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart'; +import 'package:cims_apps/features/auth/registration/view/registration_view.dart'; import 'package:cims_apps/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart'; import 'package:flutter/material.dart'; @@ -47,7 +50,7 @@ class _HomeViewState extends State { InvestType('Sharia', PathAssets.iconPortofolioSharia) ]; - StepVerification listStepVerification = StepVerification(1, [ + StepVerification listStepVerification = StepVerification(0, [ 'Registration', 'Verification', 'Complete' ]); @@ -268,106 +271,139 @@ class _HomeViewState extends State { const SizedBox( height: 24, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Row( - children: [ - Icon(Icons.verified, size: 18,), - SizedBox( - width: 12, - ), - Text( - 'Verified by PT Gemilang', - style: TextStyle( - color: ColorPalette.slate500 - ), - ) - ], - ), - Container( - width: 16, - height: 16, - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), - shape: BoxShape.circle - ), - ) - ], - ), - const SizedBox( - height: 16, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Icon(Icons.verified, size: 18,), - SizedBox( - width: 12, - ), - Text( - 'Verified by KSEI', - style: TextStyle( - color: ColorPalette.slate500 - ), - ) - ], - ), - Container( - width: 16, - height: 16, - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), - shape: BoxShape.circle - ), - ) - ], - ), - const SizedBox( - height: 16, - ), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: ColorPalette.blue50, - borderRadius: BorderRadius.circular(12) - ), - child: const Column( + if(listStepVerification.currentStep == 1)...[ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Your registration is currently being verified by PT Gemilang', - style: TextStyle( - color: ColorPalette.slate500 - ), - ), - SizedBox( - height: 16, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + const Row( children: [ - Text('Estimated:', - style: TextStyle( - color: ColorPalette.slate500 - ), + Icon(Icons.verified, size: 18,), + SizedBox( + width: 12, ), Text( - 'January 30 2024', + 'Verified by PT Gemilang', style: TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xff1E293B) + color: ColorPalette.slate500 ), ) ], + ), + Container( + width: 16, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), + shape: BoxShape.circle + ), ) ], ), - ) + const SizedBox( + height: 16, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Icon(Icons.verified, size: 18,), + SizedBox( + width: 12, + ), + Text( + 'Verified by KSEI', + style: TextStyle( + color: ColorPalette.slate500 + ), + ) + ], + ), + Container( + width: 16, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: const Color(0xffCBD5E1), width: 1.5), + shape: BoxShape.circle + ), + ) + ], + ), + const SizedBox( + height: 16, + ), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: ColorPalette.blue50, + borderRadius: BorderRadius.circular(12) + ), + child: const Column( + children: [ + Text( + 'Your registration is currently being verified by PT Gemilang', + style: TextStyle( + color: ColorPalette.slate500 + ), + ), + SizedBox( + height: 16, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Estimated:', + style: TextStyle( + color: ColorPalette.slate500 + ), + ), + Text( + 'January 30 2024', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xff1E293B) + ), + ) + ], + ) + ], + ), + ) + ]else if(listStepVerification.currentStep == 0)...[ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: ColorPalette.blue50, + borderRadius: BorderRadius.circular(12) + ), + child: Column( + children: [ + Text( + "Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia", + style: TextStyle( + color: ColorPalette.slate500 + ), + ), + SizedBox( + height: 16, + ), + ButtonView( + name: 'Registration', + width: SizeConfig.width, + marginVertical: 0, + heightWrapContent: true, + contentPadding: EdgeInsets.all(12), + onPressed: () { + routePush(context, page: InitialRegistrationStep()); + }, + ) + ], + ), + ) + ] ], ), ); @@ -515,9 +551,15 @@ class _HomeViewState extends State { padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), - color: ColorPalette.colorSwitchButtonActive + color: ColorPalette.green100 + ), + child: Text( + article.type, + style: TextStyle( + fontWeight: FontWeight.w600, + color: ColorPalette.green500 + ), ), - child: Text(article.type), ), ], ) diff --git a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart index afc11de..8ce0621 100644 --- a/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart +++ b/lib/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + 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'; @@ -5,11 +7,12 @@ import 'package:cims_apps/core/utils/size_config.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; -class CategoryPortofolio { +class InvestmentType { String name; int value; + int mutualFunds; - CategoryPortofolio(this.value, this.name); + InvestmentType(this.value, this.name, this.mutualFunds); } class PortofolioView extends StatefulWidget { @@ -36,11 +39,11 @@ class _PortofolioViewState extends State { bool seePortofolioValue = false; int touchedIndex = -1; - List listCategoryPortofolio = [ - CategoryPortofolio(20, 'Money Market'), - CategoryPortofolio(15, 'Shares'), - CategoryPortofolio(8, 'Bonds'), - CategoryPortofolio(50, 'Sharia'), + List listInvestmentType = [ + InvestmentType(20, 'Money Market', 2), + InvestmentType(15, 'Shares', 5), + InvestmentType(8, 'Bonds', 3), + InvestmentType(50, 'Sharia', 4), ]; List assetsImage = [ @@ -91,7 +94,7 @@ class _PortofolioViewState extends State { topRight: Radius.circular(24)), ), child: ListView( - padding: const EdgeInsets.symmetric(vertical: 0), + padding: const EdgeInsets.symmetric(vertical: 16), children: [ Stack(alignment: Alignment.center, children: [ AspectRatio( @@ -117,16 +120,25 @@ class _PortofolioViewState extends State { show: true, ), sectionsSpace: 20, - centerSpaceRadius: 100, + centerSpaceRadius: 110, sections: sectionsDataPortofolio())), ), - const Column( + Column( children: [ - Text('Total Mutual Fund'), - Text('10', - style: TextStyle( - fontSize: 44, - fontWeight: FontWeight.w700)), + const Text('Total Mutual Fund', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 18, + color: ColorPalette.slate400 + ), + ), + Text(listInvestmentType.map((e) => e.mutualFunds).reduce((value, element) => value + element).toString(), + style: const TextStyle( + fontSize: 44, + fontWeight: FontWeight.w700 + ) + ) + , ], ) ]), @@ -138,9 +150,6 @@ class _PortofolioViewState extends State { height: 24, ), ...listColumnPortofolio(), - const SizedBox( - height: 24, - ) ], ), ), @@ -223,7 +232,7 @@ class _PortofolioViewState extends State { } List sectionsDataPortofolio() { - return listCategoryPortofolio.asMap().entries.map((e) { + return listInvestmentType.asMap().entries.map((e) { final isTouched = e.key == touchedIndex; final radius = isTouched ? 40.0 : 30.0; return PieChartSectionData( @@ -256,7 +265,7 @@ class _PortofolioViewState extends State { child: Wrap( alignment: WrapAlignment.center, spacing: 12, - children: listCategoryPortofolio.asMap().entries.map((e) { + children: listInvestmentType.asMap().entries.map((e) { return Container( color: Colors.white, width: SizeConfig.width * 0.18, @@ -294,7 +303,7 @@ class _PortofolioViewState extends State { } List listColumnPortofolio() { - return listCategoryPortofolio.asMap().entries.map((e) { + return listInvestmentType.asMap().entries.map((e) { return Column( children: [ if (e.key > 0) ...[ @@ -316,7 +325,7 @@ class _PortofolioViewState extends State { style: const TextStyle(fontWeight: FontWeight.w600), ), subtitle: Text( - e.value.name, + '${e.value.mutualFunds} Mutual Funds', style: const TextStyle( fontWeight: FontWeight.w600, color: Color(0xff94A3B8)), ), diff --git a/lib/features/dashboard/dashboard_account/view/product/product_chart_view.dart b/lib/features/dashboard/dashboard_account/view/product/product_chart_view.dart index 186e06e..c7f5ea6 100644 --- a/lib/features/dashboard/dashboard_account/view/product/product_chart_view.dart +++ b/lib/features/dashboard/dashboard_account/view/product/product_chart_view.dart @@ -124,22 +124,13 @@ class _ProductChartViewState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 48), + padding: const EdgeInsets.only(top: 48, bottom: 24), child: AspectRatio( aspectRatio: 2.5, child: LayoutBuilder( builder: (context, constraints) { return LineChart( LineChartData( - // showingTooltipIndicators: showingTooltipOnSpots.map((index) { - // return ShowingTooltipIndicators([ - // LineBarSpot( - // tooltipsOnBar, - // lineBarsData.indexOf(tooltipsOnBar), - // tooltipsOnBar.spots[index], - // ), - // ]); - // }).toList(), extraLinesData: ExtraLinesData( verticalLines: [ VerticalLine( diff --git a/lib/features/dashboard/dashboard_account/view/product/product_view.dart b/lib/features/dashboard/dashboard_account/view/product/product_view.dart index 5502cb3..34d930d 100644 --- a/lib/features/dashboard/dashboard_account/view/product/product_view.dart +++ b/lib/features/dashboard/dashboard_account/view/product/product_view.dart @@ -99,8 +99,6 @@ class _ProductViewState extends State { Widget build(BuildContext context) { return Scaffold( body: SizedBox( - width: SizeConfig.width, - height: SizeConfig.height, child: Stack( children: [ const ImageView(image: PathAssets.imgDashboardAccount), @@ -141,7 +139,8 @@ class _ProductViewState extends State { ], ), ), - bottomNavigationBar: Padding( + bottomNavigationBar: Container( + height: SizeConfig.height * .1, padding: const EdgeInsets.symmetric(horizontal: 24), child: ButtonView( name: 'Buy', @@ -275,7 +274,7 @@ class _ProductViewState extends State { ), cardInformation('Time Machine', timeMachine()), const SizedBox( - height: 24, + height: 32, ), topFiveHoldings(), const SizedBox( @@ -498,6 +497,9 @@ class _ProductViewState extends State { ) ], ), + SizedBox( + height: 16, + ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -523,11 +525,12 @@ class _ProductViewState extends State { onPressed: () { }, - prefixIcon: Icon(Icons.space_dashboard_sharp), + prefixIcon: Icon(Icons.calendar_month_rounded), backgroundColor: ColorPalette.blue50, sizeBorderRadius: 8, isSecondaryColor: false, width: SizeConfig.width * .5, + marginVertical: 0, heightWrapContent: true, isOutlined: true, widthPrefix: 10, @@ -552,6 +555,7 @@ class _ProductViewState extends State { heightWrapContent: true, backgroundColor: ColorPalette.orange50, sizeBorderRadius: 8, + marginVertical: 0, isOutlined: true, borderColor: ColorPalette.orange500, textSize: 14, @@ -590,6 +594,8 @@ class _ProductViewState extends State { TextFormView( name: '', ctrl: machineController, + keyboardType: TextInputType.number, + contentPadding: EdgeInsets.all(12), onChanged: (value) { value = value.replaceAll('Rp ', '').replaceAll('.', ''); double parseValue = double.parse(value); @@ -600,7 +606,6 @@ class _ProductViewState extends State { } setEstimatedValue(); }, - keyboardType: TextInputType.number, ), const Padding( padding: EdgeInsets.only(top: 16, bottom: 8), diff --git a/lib/features/dashboard/dashboard_public/view/dashboard_public_view.dart b/lib/features/dashboard/dashboard_public/view/dashboard_public_view.dart index 4be6827..c20971f 100644 --- a/lib/features/dashboard/dashboard_public/view/dashboard_public_view.dart +++ b/lib/features/dashboard/dashboard_public/view/dashboard_public_view.dart @@ -4,6 +4,7 @@ import 'package:cims_apps/application/component/image/image_view.dart'; import 'package:cims_apps/application/theme/color_palette.dart'; import 'package:cims_apps/core/route/route.dart'; import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:cims_apps/features/auth/login/view/login_view.dart'; import 'package:cims_apps/features/auth/registration/view/registration_view.dart'; import 'package:cims_apps/features/bottom_navigation_view.dart'; import 'package:flutter/material.dart'; @@ -70,7 +71,7 @@ class DashboardPublicView extends StatelessWidget { width: SizeConfig.width * .43, height: SizeConfig.height * .06, onPressed: () { - routePush(context, page: const BottomNavigationView()); + routePush(context, page: const LoginView()); }, ), ButtonView( diff --git a/lib/features/splash_screen.dart b/lib/features/splash_screen.dart index 277276b..30143fc 100644 --- a/lib/features/splash_screen.dart +++ b/lib/features/splash_screen.dart @@ -17,7 +17,7 @@ class _SplashScreenState extends State { @override void initState() { Future.delayed(const Duration(seconds: 3)).then( - (value) => routePush(context, page: const DashboardPublicView()), + (value) => routePush(context, page: const DashboardPublicView(), routeType: RouteType.pushRemove), ); super.initState(); } diff --git a/lib/main.dart b/lib/main.dart index 87a7b1c..2755a41 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -28,6 +28,7 @@ class MyApp extends StatelessWidget { titleTextStyle: TextStyle( fontSize: 20, fontWeight: FontWeight.w700, + fontFamily: 'Manrope', color: ColorPalette.slate800, )), fontFamily: 'Manrope',