From 9475767021fa7893b3cc0f4b741de132989d573c Mon Sep 17 00:00:00 2001 From: Prajna Prayoga Date: Wed, 7 Feb 2024 14:44:40 +0700 Subject: [PATCH] feat: login view --- .../component/button/button_back.dart | 11 +- .../component/text_form/text_form_view.dart | 4 + lib/application/theme/color_palette.dart | 1 - lib/features/auth/login/view/login_view.dart | 94 +++++++++++++++ .../auth/login/view/password_view.dart | 80 +++++++++++++ .../auth/login/view/phone_number_view.dart | 111 ++++++++++++++++++ .../login/view_model/login_view_model.dart | 10 ++ .../view/homepage/homepage_view.dart | 10 +- .../view/dashboard_public_view.dart | 3 +- lib/main.dart | 1 + 10 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 lib/features/auth/login/view/login_view.dart create mode 100644 lib/features/auth/login/view/password_view.dart create mode 100644 lib/features/auth/login/view/phone_number_view.dart create mode 100644 lib/features/auth/login/view_model/login_view_model.dart diff --git a/lib/application/component/button/button_back.dart b/lib/application/component/button/button_back.dart index 091b8bb..9f2db7f 100644 --- a/lib/application/component/button/button_back.dart +++ b/lib/application/component/button/button_back.dart @@ -1,17 +1,22 @@ +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; + const ButtonBack({super.key, this.margin}); @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); diff --git a/lib/application/component/text_form/text_form_view.dart b/lib/application/component/text_form/text_form_view.dart index 8617893..3a22c0e 100644 --- a/lib/application/component/text_form/text_form_view.dart +++ b/lib/application/component/text_form/text_form_view.dart @@ -95,6 +95,8 @@ class TextFormView extends StatelessWidget { name, style: const TextStyle( fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate800 // color: ColorPalette.greyLight, ), ), @@ -112,6 +114,8 @@ class TextFormView extends StatelessWidget { name, style: const TextStyle( fontSize: 16, + fontWeight: FontWeight.w600, + color: ColorPalette.slate800 ), ) : const SizedBox(), diff --git a/lib/application/theme/color_palette.dart b/lib/application/theme/color_palette.dart index e4d255b..584a872 100644 --- a/lib/application/theme/color_palette.dart +++ b/lib/application/theme/color_palette.dart @@ -73,7 +73,6 @@ 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); 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..f00edf9 --- /dev/null +++ b/lib/features/auth/login/view/login_view.dart @@ -0,0 +1,94 @@ +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/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 Up'), + SizedBox( + width: SizeConfig.width * 0.1, + ) + ], + ), + shape: const RoundedRectangleBorder( + side: BorderSide(color: ColorPalette.slate200) + ), + ), + body: PageView( + 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: BottomNavigationView(), routeType: RouteType.pushRemove); + } + } +} 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..2a0bc73 --- /dev/null +++ b/lib/features/auth/login/view/password_view.dart @@ -0,0 +1,80 @@ +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 phone number', fontSize: 24), + SizedBox( + height: 24, + ), + TextFormView( + name: 'Password', + ctrl: controller, + obscureText: !provider.showPassword, + prefix: SizedBox( + width: 16, + ), + 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..33f377f --- /dev/null +++ b/lib/features/auth/login/view/phone_number_view.dart @@ -0,0 +1,111 @@ +import 'package:cims_apps/application/assets/path_assets.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/image/image_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/component/text_title/text_title.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.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: () { + + }, + 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/dashboard/dashboard_account/view/homepage/homepage_view.dart b/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart index 8b35382..891604f 100644 --- a/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart +++ b/lib/features/dashboard/dashboard_account/view/homepage/homepage_view.dart @@ -515,9 +515,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_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/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',