From 5f0284a9e5315f77868ca7613a8d30f4ca16d691 Mon Sep 17 00:00:00 2001 From: efrilm Date: Fri, 29 Aug 2025 16:14:02 +0700 Subject: [PATCH] feat: create password page --- lib/presentation/components/field/field.dart | 1 + .../field/password_text_form_page.dart | 97 +++++++ .../create_password/create_password_page.dart | 50 ++++ lib/presentation/pages/auth/otp/otp_page.dart | 18 +- lib/presentation/router/app_router.dart | 1 + lib/presentation/router/app_router.gr.dart | 264 ++++++++++-------- 6 files changed, 291 insertions(+), 140 deletions(-) create mode 100644 lib/presentation/components/field/password_text_form_page.dart create mode 100644 lib/presentation/pages/auth/create_password/create_password_page.dart diff --git a/lib/presentation/components/field/field.dart b/lib/presentation/components/field/field.dart index ea206a2..c76a3ea 100644 --- a/lib/presentation/components/field/field.dart +++ b/lib/presentation/components/field/field.dart @@ -4,3 +4,4 @@ import '../../../common/theme/theme.dart'; part 'text_form_field.dart'; part 'search_text_form_field.dart'; +part 'password_text_form_page.dart'; diff --git a/lib/presentation/components/field/password_text_form_page.dart b/lib/presentation/components/field/password_text_form_page.dart new file mode 100644 index 0000000..fdb5f58 --- /dev/null +++ b/lib/presentation/components/field/password_text_form_page.dart @@ -0,0 +1,97 @@ +part of 'field.dart'; + +class AppPasswordTextFormField extends StatefulWidget { + const AppPasswordTextFormField({ + super.key, + this.hintText, + required this.title, + this.controller, + this.focusNode, + this.prefixIcon, + this.keyboardType, + this.onChanged, + }); + + final String? hintText; + final String title; + final TextEditingController? controller; + final FocusNode? focusNode; + final Widget? prefixIcon; + final TextInputType? keyboardType; + final ValueChanged? onChanged; + + @override + State createState() => + _AppPasswordTextFormFieldState(); +} + +class _AppPasswordTextFormFieldState extends State { + bool isPasswordVisible = false; + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.title, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600), + ), + const SizedBox(height: 8), + TextFormField( + controller: widget.controller, + focusNode: widget.focusNode, + keyboardType: widget.keyboardType, + onChanged: widget.onChanged, + cursorColor: AppColor.primary, + obscureText: isPasswordVisible, + style: AppStyle.md.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.w500, + ), + decoration: InputDecoration( + hintText: widget.hintText, + prefixIcon: widget.prefixIcon, + suffixIcon: isPasswordVisible + ? IconButton( + icon: Icon( + Icons.visibility, + color: AppColor.primary, + size: 20, + ), + constraints: const BoxConstraints(), + padding: const EdgeInsets.all(8), + onPressed: () { + setState(() { + isPasswordVisible = !isPasswordVisible; + }); + }, + ) + : IconButton( + icon: Icon( + Icons.visibility_off, + color: AppColor.primary, + size: 20, + ), + constraints: const BoxConstraints(), + padding: const EdgeInsets.all(8), + onPressed: () { + setState(() { + isPasswordVisible = !isPasswordVisible; + }); + }, + ), + + prefixIconConstraints: const BoxConstraints( + minWidth: 0, + minHeight: 0, + ), + suffixIconConstraints: const BoxConstraints( + minWidth: 0, + minHeight: 0, + ), + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/auth/create_password/create_password_page.dart b/lib/presentation/pages/auth/create_password/create_password_page.dart new file mode 100644 index 0000000..a8ec3a2 --- /dev/null +++ b/lib/presentation/pages/auth/create_password/create_password_page.dart @@ -0,0 +1,50 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../components/button/button.dart'; +import '../../../components/field/field.dart'; +import '../../../router/app_router.gr.dart'; + +@RoutePage() +class CreatePasswordPage extends StatelessWidget { + const CreatePasswordPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Buat Kata Sandi')), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 40), + + // Title + AppPasswordTextFormField( + title: 'Masukkan kata sandi', + hintText: '********', + ), + SizedBox(height: 24), + AppPasswordTextFormField( + title: 'Ulangi kata sandi', + hintText: '********', + ), + + const SizedBox(height: 50), + + Spacer(), + + // Continue Button + AppElevatedButton( + onPressed: () => context.router.push(const MainRoute()), + title: 'Konfirmasi', + ), + + const SizedBox(height: 24), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/auth/otp/otp_page.dart b/lib/presentation/pages/auth/otp/otp_page.dart index 31ac7da..e83da2d 100644 --- a/lib/presentation/pages/auth/otp/otp_page.dart +++ b/lib/presentation/pages/auth/otp/otp_page.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../../common/theme/theme.dart'; -import '../../../components/button/button.dart'; import '../../../router/app_router.gr.dart'; @RoutePage() @@ -83,7 +82,7 @@ class _OtpPageState extends State { void _verifyCode() { String code = _controllers.map((controller) => controller.text).join(); if (code.length == 6) { - context.router.push(PinRoute(isCreatePin: true)); + context.router.push(CreatePasswordRoute()); } } @@ -228,21 +227,6 @@ class _OtpPageState extends State { ), ], - const Spacer(), - - // Continue Button - AppElevatedButton( - title: 'Verifikasi', - onPressed: () { - String code = _controllers - .map((controller) => controller.text) - .join(); - if (code.length == 6) { - _verifyCode(); - } - }, - ), - const SizedBox(height: 24), ], ), diff --git a/lib/presentation/router/app_router.dart b/lib/presentation/router/app_router.dart index eeca603..5d5975c 100644 --- a/lib/presentation/router/app_router.dart +++ b/lib/presentation/router/app_router.dart @@ -16,6 +16,7 @@ class AppRouter extends RootStackRouter { AutoRoute(page: RegisterRoute.page), AutoRoute(page: OtpRoute.page), AutoRoute(page: PinRoute.page), + AutoRoute(page: CreatePasswordRoute.page), // Main AutoRoute( diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index 4417d93..fb8bf15 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -9,42 +9,60 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i18; -import 'package:enaklo/presentation/pages/auth/login/login_page.dart' as _i4; -import 'package:enaklo/presentation/pages/auth/otp/otp_page.dart' as _i10; -import 'package:enaklo/presentation/pages/auth/pin/pin_page.dart' as _i11; -import 'package:enaklo/presentation/pages/auth/register/register_page.dart' - as _i14; -import 'package:enaklo/presentation/pages/draw/draw_page.dart' as _i2; -import 'package:enaklo/presentation/pages/draw/pages/draw_detail/draw_detail_page.dart' +import 'package:auto_route/auto_route.dart' as _i19; +import 'package:enaklo/presentation/pages/auth/create_password/create_password_page.dart' as _i1; -import 'package:enaklo/presentation/pages/main/main_page.dart' as _i5; +import 'package:enaklo/presentation/pages/auth/login/login_page.dart' as _i5; +import 'package:enaklo/presentation/pages/auth/otp/otp_page.dart' as _i11; +import 'package:enaklo/presentation/pages/auth/pin/pin_page.dart' as _i12; +import 'package:enaklo/presentation/pages/auth/register/register_page.dart' + as _i15; +import 'package:enaklo/presentation/pages/draw/draw_page.dart' as _i3; +import 'package:enaklo/presentation/pages/draw/pages/draw_detail/draw_detail_page.dart' + as _i2; +import 'package:enaklo/presentation/pages/main/main_page.dart' as _i6; import 'package:enaklo/presentation/pages/main/pages/home/home_page.dart' - as _i3; + as _i4; import 'package:enaklo/presentation/pages/main/pages/order/order_page.dart' - as _i9; + as _i10; import 'package:enaklo/presentation/pages/main/pages/profile/profile_page.dart' - as _i13; + as _i14; import 'package:enaklo/presentation/pages/main/pages/voucher/voucher_page.dart' - as _i17; -import 'package:enaklo/presentation/pages/merchant/merchant_page.dart' as _i7; + as _i18; +import 'package:enaklo/presentation/pages/merchant/merchant_page.dart' as _i8; import 'package:enaklo/presentation/pages/merchant/pages/merchant_detail/merchant_detail_page.dart' - as _i6; + as _i7; import 'package:enaklo/presentation/pages/onboarding/onboarding_page.dart' - as _i8; + as _i9; import 'package:enaklo/presentation/pages/reward/pages/product_redeem/product_redeem_page.dart' - as _i12; -import 'package:enaklo/presentation/pages/reward/reward_page.dart' as _i15; -import 'package:enaklo/presentation/pages/splash/splash_page.dart' as _i16; -import 'package:flutter/material.dart' as _i19; + as _i13; +import 'package:enaklo/presentation/pages/reward/reward_page.dart' as _i16; +import 'package:enaklo/presentation/pages/splash/splash_page.dart' as _i17; +import 'package:flutter/material.dart' as _i20; /// generated route for -/// [_i1.DrawDetailPage] -class DrawDetailRoute extends _i18.PageRouteInfo { +/// [_i1.CreatePasswordPage] +class CreatePasswordRoute extends _i19.PageRouteInfo { + const CreatePasswordRoute({List<_i19.PageRouteInfo>? children}) + : super(CreatePasswordRoute.name, initialChildren: children); + + static const String name = 'CreatePasswordRoute'; + + static _i19.PageInfo page = _i19.PageInfo( + name, + builder: (data) { + return const _i1.CreatePasswordPage(); + }, + ); +} + +/// generated route for +/// [_i2.DrawDetailPage] +class DrawDetailRoute extends _i19.PageRouteInfo { DrawDetailRoute({ - _i19.Key? key, - required _i2.DrawEvent drawEvent, - List<_i18.PageRouteInfo>? children, + _i20.Key? key, + required _i3.DrawEvent drawEvent, + List<_i19.PageRouteInfo>? children, }) : super( DrawDetailRoute.name, args: DrawDetailRouteArgs(key: key, drawEvent: drawEvent), @@ -53,11 +71,11 @@ class DrawDetailRoute extends _i18.PageRouteInfo { static const String name = 'DrawDetailRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i1.DrawDetailPage(key: args.key, drawEvent: args.drawEvent); + return _i2.DrawDetailPage(key: args.key, drawEvent: args.drawEvent); }, ); } @@ -65,9 +83,9 @@ class DrawDetailRoute extends _i18.PageRouteInfo { class DrawDetailRouteArgs { const DrawDetailRouteArgs({this.key, required this.drawEvent}); - final _i19.Key? key; + final _i20.Key? key; - final _i2.DrawEvent drawEvent; + final _i3.DrawEvent drawEvent; @override String toString() { @@ -76,76 +94,76 @@ class DrawDetailRouteArgs { } /// generated route for -/// [_i2.DrawPage] -class DrawRoute extends _i18.PageRouteInfo { - const DrawRoute({List<_i18.PageRouteInfo>? children}) +/// [_i3.DrawPage] +class DrawRoute extends _i19.PageRouteInfo { + const DrawRoute({List<_i19.PageRouteInfo>? children}) : super(DrawRoute.name, initialChildren: children); static const String name = 'DrawRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i2.DrawPage(); + return const _i3.DrawPage(); }, ); } /// generated route for -/// [_i3.HomePage] -class HomeRoute extends _i18.PageRouteInfo { - const HomeRoute({List<_i18.PageRouteInfo>? children}) +/// [_i4.HomePage] +class HomeRoute extends _i19.PageRouteInfo { + const HomeRoute({List<_i19.PageRouteInfo>? children}) : super(HomeRoute.name, initialChildren: children); static const String name = 'HomeRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i3.HomePage(); + return const _i4.HomePage(); }, ); } /// generated route for -/// [_i4.LoginPage] -class LoginRoute extends _i18.PageRouteInfo { - const LoginRoute({List<_i18.PageRouteInfo>? children}) +/// [_i5.LoginPage] +class LoginRoute extends _i19.PageRouteInfo { + const LoginRoute({List<_i19.PageRouteInfo>? children}) : super(LoginRoute.name, initialChildren: children); static const String name = 'LoginRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i4.LoginPage(); + return const _i5.LoginPage(); }, ); } /// generated route for -/// [_i5.MainPage] -class MainRoute extends _i18.PageRouteInfo { - const MainRoute({List<_i18.PageRouteInfo>? children}) +/// [_i6.MainPage] +class MainRoute extends _i19.PageRouteInfo { + const MainRoute({List<_i19.PageRouteInfo>? children}) : super(MainRoute.name, initialChildren: children); static const String name = 'MainRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i5.MainPage(); + return const _i6.MainPage(); }, ); } /// generated route for -/// [_i6.MerchantDetailPage] -class MerchantDetailRoute extends _i18.PageRouteInfo { +/// [_i7.MerchantDetailPage] +class MerchantDetailRoute extends _i19.PageRouteInfo { MerchantDetailRoute({ - _i19.Key? key, - required _i7.MerchantModel merchant, - List<_i18.PageRouteInfo>? children, + _i20.Key? key, + required _i8.MerchantModel merchant, + List<_i19.PageRouteInfo>? children, }) : super( MerchantDetailRoute.name, args: MerchantDetailRouteArgs(key: key, merchant: merchant), @@ -154,11 +172,11 @@ class MerchantDetailRoute extends _i18.PageRouteInfo { static const String name = 'MerchantDetailRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i6.MerchantDetailPage(key: args.key, merchant: args.merchant); + return _i7.MerchantDetailPage(key: args.key, merchant: args.merchant); }, ); } @@ -166,9 +184,9 @@ class MerchantDetailRoute extends _i18.PageRouteInfo { class MerchantDetailRouteArgs { const MerchantDetailRouteArgs({this.key, required this.merchant}); - final _i19.Key? key; + final _i20.Key? key; - final _i7.MerchantModel merchant; + final _i8.MerchantModel merchant; @override String toString() { @@ -177,77 +195,77 @@ class MerchantDetailRouteArgs { } /// generated route for -/// [_i7.MerchantPage] -class MerchantRoute extends _i18.PageRouteInfo { - const MerchantRoute({List<_i18.PageRouteInfo>? children}) +/// [_i8.MerchantPage] +class MerchantRoute extends _i19.PageRouteInfo { + const MerchantRoute({List<_i19.PageRouteInfo>? children}) : super(MerchantRoute.name, initialChildren: children); static const String name = 'MerchantRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i7.MerchantPage(); + return const _i8.MerchantPage(); }, ); } /// generated route for -/// [_i8.OnboardingPage] -class OnboardingRoute extends _i18.PageRouteInfo { - const OnboardingRoute({List<_i18.PageRouteInfo>? children}) +/// [_i9.OnboardingPage] +class OnboardingRoute extends _i19.PageRouteInfo { + const OnboardingRoute({List<_i19.PageRouteInfo>? children}) : super(OnboardingRoute.name, initialChildren: children); static const String name = 'OnboardingRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i8.OnboardingPage(); + return const _i9.OnboardingPage(); }, ); } /// generated route for -/// [_i9.OrderPage] -class OrderRoute extends _i18.PageRouteInfo { - const OrderRoute({List<_i18.PageRouteInfo>? children}) +/// [_i10.OrderPage] +class OrderRoute extends _i19.PageRouteInfo { + const OrderRoute({List<_i19.PageRouteInfo>? children}) : super(OrderRoute.name, initialChildren: children); static const String name = 'OrderRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i9.OrderPage(); + return const _i10.OrderPage(); }, ); } /// generated route for -/// [_i10.OtpPage] -class OtpRoute extends _i18.PageRouteInfo { - const OtpRoute({List<_i18.PageRouteInfo>? children}) +/// [_i11.OtpPage] +class OtpRoute extends _i19.PageRouteInfo { + const OtpRoute({List<_i19.PageRouteInfo>? children}) : super(OtpRoute.name, initialChildren: children); static const String name = 'OtpRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i10.OtpPage(); + return const _i11.OtpPage(); }, ); } /// generated route for -/// [_i11.PinPage] -class PinRoute extends _i18.PageRouteInfo { +/// [_i12.PinPage] +class PinRoute extends _i19.PageRouteInfo { PinRoute({ - _i19.Key? key, + _i20.Key? key, bool isCreatePin = true, String? title, - List<_i18.PageRouteInfo>? children, + List<_i19.PageRouteInfo>? children, }) : super( PinRoute.name, args: PinRouteArgs(key: key, isCreatePin: isCreatePin, title: title), @@ -256,13 +274,13 @@ class PinRoute extends _i18.PageRouteInfo { static const String name = 'PinRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const PinRouteArgs(), ); - return _i11.PinPage( + return _i12.PinPage( key: args.key, isCreatePin: args.isCreatePin, title: args.title, @@ -274,7 +292,7 @@ class PinRoute extends _i18.PageRouteInfo { class PinRouteArgs { const PinRouteArgs({this.key, this.isCreatePin = true, this.title}); - final _i19.Key? key; + final _i20.Key? key; final bool isCreatePin; @@ -287,14 +305,14 @@ class PinRouteArgs { } /// generated route for -/// [_i12.ProductRedeemPage] -class ProductRedeemRoute extends _i18.PageRouteInfo { +/// [_i13.ProductRedeemPage] +class ProductRedeemRoute extends _i19.PageRouteInfo { ProductRedeemRoute({ - _i19.Key? key, - required _i15.Product product, - required _i15.Merchant merchant, - required _i15.PointCard pointCard, - List<_i18.PageRouteInfo>? children, + _i20.Key? key, + required _i16.Product product, + required _i16.Merchant merchant, + required _i16.PointCard pointCard, + List<_i19.PageRouteInfo>? children, }) : super( ProductRedeemRoute.name, args: ProductRedeemRouteArgs( @@ -308,11 +326,11 @@ class ProductRedeemRoute extends _i18.PageRouteInfo { static const String name = 'ProductRedeemRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i12.ProductRedeemPage( + return _i13.ProductRedeemPage( key: args.key, product: args.product, merchant: args.merchant, @@ -330,13 +348,13 @@ class ProductRedeemRouteArgs { required this.pointCard, }); - final _i19.Key? key; + final _i20.Key? key; - final _i15.Product product; + final _i16.Product product; - final _i15.Merchant merchant; + final _i16.Merchant merchant; - final _i15.PointCard pointCard; + final _i16.PointCard pointCard; @override String toString() { @@ -345,81 +363,81 @@ class ProductRedeemRouteArgs { } /// generated route for -/// [_i13.ProfilePage] -class ProfileRoute extends _i18.PageRouteInfo { - const ProfileRoute({List<_i18.PageRouteInfo>? children}) +/// [_i14.ProfilePage] +class ProfileRoute extends _i19.PageRouteInfo { + const ProfileRoute({List<_i19.PageRouteInfo>? children}) : super(ProfileRoute.name, initialChildren: children); static const String name = 'ProfileRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i13.ProfilePage(); + return const _i14.ProfilePage(); }, ); } /// generated route for -/// [_i14.RegisterPage] -class RegisterRoute extends _i18.PageRouteInfo { - const RegisterRoute({List<_i18.PageRouteInfo>? children}) +/// [_i15.RegisterPage] +class RegisterRoute extends _i19.PageRouteInfo { + const RegisterRoute({List<_i19.PageRouteInfo>? children}) : super(RegisterRoute.name, initialChildren: children); static const String name = 'RegisterRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i14.RegisterPage(); + return const _i15.RegisterPage(); }, ); } /// generated route for -/// [_i15.RewardPage] -class RewardRoute extends _i18.PageRouteInfo { - const RewardRoute({List<_i18.PageRouteInfo>? children}) +/// [_i16.RewardPage] +class RewardRoute extends _i19.PageRouteInfo { + const RewardRoute({List<_i19.PageRouteInfo>? children}) : super(RewardRoute.name, initialChildren: children); static const String name = 'RewardRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i15.RewardPage(); + return const _i16.RewardPage(); }, ); } /// generated route for -/// [_i16.SplashPage] -class SplashRoute extends _i18.PageRouteInfo { - const SplashRoute({List<_i18.PageRouteInfo>? children}) +/// [_i17.SplashPage] +class SplashRoute extends _i19.PageRouteInfo { + const SplashRoute({List<_i19.PageRouteInfo>? children}) : super(SplashRoute.name, initialChildren: children); static const String name = 'SplashRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i16.SplashPage(); + return const _i17.SplashPage(); }, ); } /// generated route for -/// [_i17.VoucherPage] -class VoucherRoute extends _i18.PageRouteInfo { - const VoucherRoute({List<_i18.PageRouteInfo>? children}) +/// [_i18.VoucherPage] +class VoucherRoute extends _i19.PageRouteInfo { + const VoucherRoute({List<_i19.PageRouteInfo>? children}) : super(VoucherRoute.name, initialChildren: children); static const String name = 'VoucherRoute'; - static _i18.PageInfo page = _i18.PageInfo( + static _i19.PageInfo page = _i19.PageInfo( name, builder: (data) { - return const _i17.VoucherPage(); + return const _i18.VoucherPage(); }, ); }