feat: change password

This commit is contained in:
efrilm
2025-08-19 15:35:18 +07:00
parent 7919825955
commit 1b1e8c5bb4
14 changed files with 1247 additions and 119 deletions
@@ -0,0 +1,104 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/user/change_password_form/change_password_form_bloc.dart';
import '../../../../../common/theme/theme.dart';
import '../../../../../injection.dart';
import '../../../../components/appbar/appbar.dart';
import '../../../../components/button/button.dart';
import '../../../../components/spacer/spacer.dart';
import '../../../../components/toast/flushbar.dart';
import 'widgets/current_password.dart';
import 'widgets/new_password.dart';
@RoutePage()
class ProfileChangePasswordPage extends StatefulWidget
implements AutoRouteWrapper {
const ProfileChangePasswordPage({super.key});
@override
State<ProfileChangePasswordPage> createState() =>
_ProfileChangePasswordPageState();
@override
Widget wrappedRoute(BuildContext context) =>
BlocProvider(create: (_) => getIt<ChangePasswordFormBloc>(), child: this);
}
class _ProfileChangePasswordPageState extends State<ProfileChangePasswordPage> {
@override
Widget build(BuildContext context) {
return BlocListener<ChangePasswordFormBloc, ChangePasswordFormState>(
listener: (context, state) {
state.failureOrChangePasswordOption.fold(
() => null,
(either) => either.fold(
(f) => AppFlushbar.showUserFailureToast(context, f),
(user) {
if (context.mounted) {
AppFlushbar.showSuccess(context, 'Password changed');
Future.delayed(const Duration(seconds: 2), () {
context.router.back();
});
}
},
),
);
},
child: Scaffold(
backgroundColor: AppColor.background,
body: CustomScrollView(
slivers: [
// SliverAppBar with gradient
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
elevation: 0,
backgroundColor: AppColor.primary,
flexibleSpace: CustomAppBar(title: 'Change Password'),
),
SliverToBoxAdapter(
child:
BlocBuilder<ChangePasswordFormBloc, ChangePasswordFormState>(
builder: (context, state) {
return Container(
margin: EdgeInsets.all(AppValue.margin),
padding: EdgeInsets.all(AppValue.padding),
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(AppValue.radius),
),
child: Form(
autovalidateMode: state.showErrorMessages
? AutovalidateMode.always
: AutovalidateMode.disabled,
child: Column(
children: [
ChangePasswordCurrentPassword(),
SpaceHeight(16),
ChangePasswordNewPassword(),
SpaceHeight(24),
AppElevatedButton(
text: 'Save',
isLoading: state.isSubmitting,
onPressed: () {
context.read<ChangePasswordFormBloc>().add(
ChangePasswordFormEvent.submitted(),
);
},
),
],
),
),
);
},
),
),
],
),
),
);
}
}
@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:line_icons/line_icons.dart';
import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart';
import '../../../../../components/field/field.dart';
class ChangePasswordCurrentPassword extends StatelessWidget {
const ChangePasswordCurrentPassword({super.key});
@override
Widget build(BuildContext context) {
return AppPasswordTextFormField(
title: 'Current Password',
prefixIcon: LineIcons.lock,
hintText: 'Please enter your current password',
onChanged: (value) => context.read<ChangePasswordFormBloc>().add(
ChangePasswordFormEvent.currentPasswordChanged(value),
),
validator: (value) {
if (context
.read<ChangePasswordFormBloc>()
.state
.currentPassword
.isEmpty) {
return 'Please enter your current password';
}
return null;
},
);
}
}
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:line_icons/line_icons.dart';
import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart';
import '../../../../../components/field/field.dart';
class ChangePasswordNewPassword extends StatelessWidget {
const ChangePasswordNewPassword({super.key});
@override
Widget build(BuildContext context) {
return AppPasswordTextFormField(
title: 'New Password',
prefixIcon: LineIcons.lock,
hintText: 'Please enter your new password',
onChanged: (value) => context.read<ChangePasswordFormBloc>().add(
ChangePasswordFormEvent.newPasswordChanged(value),
),
validator: (value) {
if (context.read<ChangePasswordFormBloc>().state.newPassword.isEmpty) {
return 'Please enter your new password';
}
if (context.read<ChangePasswordFormBloc>().state.newPassword ==
context.read<ChangePasswordFormBloc>().state.currentPassword) {
return 'New password cannot be same as current password';
}
return null;
},
);
}
}
@@ -66,6 +66,13 @@ class ProfileAccountInfo extends StatelessWidget {
subtitle: 'Ubah profil kamu',
onTap: () => context.router.push(ProfileEditRoute(user: user)),
),
ProfileDivider(),
ProfileTile(
icon: LineIcons.lock,
title: 'Change Password',
subtitle: 'Change your password',
onTap: () => context.router.push(ProfileChangePasswordRoute()),
),
],
),
);