From c2f0d75a17a623e9ebe4c675e96aeb47baf5a268 Mon Sep 17 00:00:00 2001 From: orangdeso Date: Sun, 11 May 2025 20:47:36 +0700 Subject: [PATCH] Feat: done features forget password --- .../repositories/auth_repository_impl.dart | 22 +++++++++++ lib/domain/bindings/auth_binding.dart | 4 ++ lib/domain/repositories/auth_repository.dart | 4 ++ lib/domain/usecases/auth_usecase.dart | 12 ++++++ .../controllers/auth_controller.dart | 39 ++++++++++++++----- .../auth/pages/forget_password_screen.dart | 16 ++++++-- 6 files changed, 84 insertions(+), 13 deletions(-) diff --git a/lib/data/repositories/auth_repository_impl.dart b/lib/data/repositories/auth_repository_impl.dart index 0618abe..7af7d99 100644 --- a/lib/data/repositories/auth_repository_impl.dart +++ b/lib/data/repositories/auth_repository_impl.dart @@ -115,4 +115,26 @@ class AuthRepositoryImpl implements AuthRepository { } return null; } + + @override + Future sendPasswordResetEmail(String email) async { + try { + await _firebaseAuth.sendPasswordResetEmail(email: email); + } on FirebaseAuthException catch (e) { + throw AuthException(e.message ?? "Gagal mengirim email reset."); + } + } + + @override + Future confirmPasswordReset(String code, String newPassword) async { + try { + await _firebaseAuth.verifyPasswordResetCode(code); + await _firebaseAuth.confirmPasswordReset( + code: code, + newPassword: newPassword, + ); + } on FirebaseAuthException catch (e) { + throw AuthException(e.message ?? "Gagal mengganti password."); + } + } } diff --git a/lib/domain/bindings/auth_binding.dart b/lib/domain/bindings/auth_binding.dart index 191537c..a0cd95c 100644 --- a/lib/domain/bindings/auth_binding.dart +++ b/lib/domain/bindings/auth_binding.dart @@ -15,6 +15,8 @@ class AuthBinding extends Bindings { final getUserDataUseCase = GetUserDataUseCase(authRepository); final registerUseCase = RegisterUseCase(authRepository); final saveUserDataUseCase = SaveUserDataUseCase(authRepository); + final sendResetEmailUseCase = SendResetEmailUseCase(authRepository); + final confirmResetPasswordUseCase = ConfirmResetPasswordUseCase(authRepository); Get.put( AuthController( @@ -23,6 +25,8 @@ class AuthBinding extends Bindings { getUserDataUseCase: getUserDataUseCase, registerUseCase: registerUseCase, saveUserDataUseCase: saveUserDataUseCase, + sendResetEmailUseCase: sendResetEmailUseCase, + confirmResetPasswordUseCase: confirmResetPasswordUseCase, ), ); } diff --git a/lib/domain/repositories/auth_repository.dart b/lib/domain/repositories/auth_repository.dart index f95cacd..336a9ed 100644 --- a/lib/domain/repositories/auth_repository.dart +++ b/lib/domain/repositories/auth_repository.dart @@ -9,4 +9,8 @@ abstract class AuthRepository { Future registerWithEmailPassword(String email, String password); Future saveUserData(UserData userData); + + Future sendPasswordResetEmail(String email); + Future confirmPasswordReset(String code, String newPassword); + } diff --git a/lib/domain/usecases/auth_usecase.dart b/lib/domain/usecases/auth_usecase.dart index e1bfa64..5b1c5b0 100644 --- a/lib/domain/usecases/auth_usecase.dart +++ b/lib/domain/usecases/auth_usecase.dart @@ -48,3 +48,15 @@ class SaveUserDataUseCase { return await authRepository.saveUserData(userData); } } + +class SendResetEmailUseCase { + final AuthRepository repo; + SendResetEmailUseCase(this.repo); + Future call(String email) => repo.sendPasswordResetEmail(email); +} + +class ConfirmResetPasswordUseCase { + final AuthRepository repo; + ConfirmResetPasswordUseCase(this.repo); + Future call(String code, String newPassword) => repo.confirmPasswordReset(code, newPassword); +} diff --git a/lib/presentation/controllers/auth_controller.dart b/lib/presentation/controllers/auth_controller.dart index bf0d734..0a24cec 100644 --- a/lib/presentation/controllers/auth_controller.dart +++ b/lib/presentation/controllers/auth_controller.dart @@ -16,6 +16,8 @@ class AuthController extends GetxController { final GetUserDataUseCase getUserDataUseCase; final RegisterUseCase registerUseCase; final SaveUserDataUseCase saveUserDataUseCase; + final SendResetEmailUseCase sendResetEmailUseCase; + final ConfirmResetPasswordUseCase confirmResetPasswordUseCase; final emailController = TextEditingController(); final passwordController = TextEditingController(); @@ -29,6 +31,8 @@ class AuthController extends GetxController { required this.getUserDataUseCase, required this.registerUseCase, required this.saveUserDataUseCase, + required this.sendResetEmailUseCase, + required this.confirmResetPasswordUseCase, }); Future login({String? roleFromOnboarding}) async { @@ -83,7 +87,7 @@ class AuthController extends GetxController { "Login Gagal", "Email atau password anda salah.", ); - } + } } catch (e) { SnackbarHelper.showError("Terjadi Kesalahan", e.toString()); } finally { @@ -200,13 +204,28 @@ class AuthController extends GetxController { } } - // void _showErrorSnackbar(String title, String message) { - // Get.snackbar( - // title, - // message, - // snackPosition: SnackPosition.TOP, - // backgroundColor: Colors.red, - // colorText: Colors.white, - // ); - // } + Future sendResetEmail(String email) async { + try { + await sendResetEmailUseCase(email.trim()); + SnackbarHelper.showSuccess( + "Silahkan Cek Email", + "Link reset password telah dikirim ke $email.", + ); + } on AuthException catch (e) { + SnackbarHelper.showError("Gagal", e.message); + } + } + + Future resetPassword(String code, String newPassword) async { + try { + await confirmResetPasswordUseCase(code, newPassword); + SnackbarHelper.showSuccess( + "Berhasil", + "Password berhasil diubah. Silakan login kembali.", + ); + Get.offAllNamed(Routes.LOGIN); + } on AuthException catch (e) { + SnackbarHelper.showError("Gagal", e.message); + } + } } diff --git a/lib/presentation/screens/auth/pages/forget_password_screen.dart b/lib/presentation/screens/auth/pages/forget_password_screen.dart index dfbcc7b..94eb90a 100644 --- a/lib/presentation/screens/auth/pages/forget_password_screen.dart +++ b/lib/presentation/screens/auth/pages/forget_password_screen.dart @@ -1,5 +1,8 @@ import 'package:e_porter/_core/component/button/button_fill.dart'; import 'package:e_porter/_core/component/button/button_no_fill.dart'; +import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart'; +import 'package:e_porter/_core/validators/validators.dart'; +import 'package:e_porter/presentation/controllers/auth_controller.dart'; import 'package:e_porter/presentation/screens/auth/component/header_text.dart'; import 'package:e_porter/presentation/screens/routes/app_rountes.dart'; import 'package:flutter/material.dart'; @@ -23,6 +26,7 @@ class _ForgetPasswordScreenState extends State { final String? role = Get.arguments as String; final TextEditingController emailController = TextEditingController(); final _formKey = GlobalKey(); + final authController = Get.find(); @override Widget build(BuildContext context) { @@ -57,6 +61,7 @@ class _ForgetPasswordScreenState extends State { controller: emailController, hintText: 'example@gmail.com', svgIconPath: 'assets/icons/ic_email.svg', + validator: Validators.validatorEmail, ), ], ), @@ -64,8 +69,7 @@ class _ForgetPasswordScreenState extends State { ), ), ), - bottomNavigationBar: Padding( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h), + bottomNavigationBar: CustomeShadowCotainner( child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -73,7 +77,13 @@ class _ForgetPasswordScreenState extends State { child: ButtonFill( text: 'Atur Ulang Password', textColor: Colors.white, - onTap: () {}, + onTap: () { + if (_formKey.currentState!.validate()) { + authController.sendResetEmail(emailController.text); + Get.offAllNamed(Routes.LOGIN, arguments: role); + emailController.clear(); + } + }, ), ), SizedBox(height: 10.h),