Feat: done features forget password

This commit is contained in:
orangdeso 2025-05-11 20:47:36 +07:00
parent e7d36fdaac
commit c2f0d75a17
6 changed files with 84 additions and 13 deletions

View File

@ -115,4 +115,26 @@ class AuthRepositoryImpl implements AuthRepository {
} }
return null; return null;
} }
@override
Future<void> sendPasswordResetEmail(String email) async {
try {
await _firebaseAuth.sendPasswordResetEmail(email: email);
} on FirebaseAuthException catch (e) {
throw AuthException(e.message ?? "Gagal mengirim email reset.");
}
}
@override
Future<void> 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.");
}
}
} }

View File

@ -15,6 +15,8 @@ class AuthBinding extends Bindings {
final getUserDataUseCase = GetUserDataUseCase(authRepository); final getUserDataUseCase = GetUserDataUseCase(authRepository);
final registerUseCase = RegisterUseCase(authRepository); final registerUseCase = RegisterUseCase(authRepository);
final saveUserDataUseCase = SaveUserDataUseCase(authRepository); final saveUserDataUseCase = SaveUserDataUseCase(authRepository);
final sendResetEmailUseCase = SendResetEmailUseCase(authRepository);
final confirmResetPasswordUseCase = ConfirmResetPasswordUseCase(authRepository);
Get.put<AuthController>( Get.put<AuthController>(
AuthController( AuthController(
@ -23,6 +25,8 @@ class AuthBinding extends Bindings {
getUserDataUseCase: getUserDataUseCase, getUserDataUseCase: getUserDataUseCase,
registerUseCase: registerUseCase, registerUseCase: registerUseCase,
saveUserDataUseCase: saveUserDataUseCase, saveUserDataUseCase: saveUserDataUseCase,
sendResetEmailUseCase: sendResetEmailUseCase,
confirmResetPasswordUseCase: confirmResetPasswordUseCase,
), ),
); );
} }

View File

@ -9,4 +9,8 @@ abstract class AuthRepository {
Future<UserEntity> registerWithEmailPassword(String email, String password); Future<UserEntity> registerWithEmailPassword(String email, String password);
Future<void> saveUserData(UserData userData); Future<void> saveUserData(UserData userData);
Future<void> sendPasswordResetEmail(String email);
Future<void> confirmPasswordReset(String code, String newPassword);
} }

View File

@ -48,3 +48,15 @@ class SaveUserDataUseCase {
return await authRepository.saveUserData(userData); return await authRepository.saveUserData(userData);
} }
} }
class SendResetEmailUseCase {
final AuthRepository repo;
SendResetEmailUseCase(this.repo);
Future<void> call(String email) => repo.sendPasswordResetEmail(email);
}
class ConfirmResetPasswordUseCase {
final AuthRepository repo;
ConfirmResetPasswordUseCase(this.repo);
Future<void> call(String code, String newPassword) => repo.confirmPasswordReset(code, newPassword);
}

View File

@ -16,6 +16,8 @@ class AuthController extends GetxController {
final GetUserDataUseCase getUserDataUseCase; final GetUserDataUseCase getUserDataUseCase;
final RegisterUseCase registerUseCase; final RegisterUseCase registerUseCase;
final SaveUserDataUseCase saveUserDataUseCase; final SaveUserDataUseCase saveUserDataUseCase;
final SendResetEmailUseCase sendResetEmailUseCase;
final ConfirmResetPasswordUseCase confirmResetPasswordUseCase;
final emailController = TextEditingController(); final emailController = TextEditingController();
final passwordController = TextEditingController(); final passwordController = TextEditingController();
@ -29,6 +31,8 @@ class AuthController extends GetxController {
required this.getUserDataUseCase, required this.getUserDataUseCase,
required this.registerUseCase, required this.registerUseCase,
required this.saveUserDataUseCase, required this.saveUserDataUseCase,
required this.sendResetEmailUseCase,
required this.confirmResetPasswordUseCase,
}); });
Future<void> login({String? roleFromOnboarding}) async { Future<void> login({String? roleFromOnboarding}) async {
@ -83,7 +87,7 @@ class AuthController extends GetxController {
"Login Gagal", "Login Gagal",
"Email atau password anda salah.", "Email atau password anda salah.",
); );
} }
} catch (e) { } catch (e) {
SnackbarHelper.showError("Terjadi Kesalahan", e.toString()); SnackbarHelper.showError("Terjadi Kesalahan", e.toString());
} finally { } finally {
@ -200,13 +204,28 @@ class AuthController extends GetxController {
} }
} }
// void _showErrorSnackbar(String title, String message) { Future<void> sendResetEmail(String email) async {
// Get.snackbar( try {
// title, await sendResetEmailUseCase(email.trim());
// message, SnackbarHelper.showSuccess(
// snackPosition: SnackPosition.TOP, "Silahkan Cek Email",
// backgroundColor: Colors.red, "Link reset password telah dikirim ke $email.",
// colorText: Colors.white, );
// ); } on AuthException catch (e) {
// } SnackbarHelper.showError("Gagal", e.message);
}
}
Future<void> 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);
}
}
} }

View File

@ -1,5 +1,8 @@
import 'package:e_porter/_core/component/button/button_fill.dart'; 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/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/auth/component/header_text.dart';
import 'package:e_porter/presentation/screens/routes/app_rountes.dart'; import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -23,6 +26,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
final String? role = Get.arguments as String; final String? role = Get.arguments as String;
final TextEditingController emailController = TextEditingController(); final TextEditingController emailController = TextEditingController();
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final authController = Get.find<AuthController>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -57,6 +61,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
controller: emailController, controller: emailController,
hintText: 'example@gmail.com', hintText: 'example@gmail.com',
svgIconPath: 'assets/icons/ic_email.svg', svgIconPath: 'assets/icons/ic_email.svg',
validator: Validators.validatorEmail,
), ),
], ],
), ),
@ -64,8 +69,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
), ),
), ),
), ),
bottomNavigationBar: Padding( bottomNavigationBar: CustomeShadowCotainner(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -73,7 +77,13 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
child: ButtonFill( child: ButtonFill(
text: 'Atur Ulang Password', text: 'Atur Ulang Password',
textColor: Colors.white, 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), SizedBox(height: 10.h),