From 44b7fcbba2b60445053ec3403d4835b5a7c348e0 Mon Sep 17 00:00:00 2001 From: Alex <78383757+Lextical@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:13:57 -0600 Subject: [PATCH] added forget password --- .../activities/ForgotPasswordActivity.java | 50 ++++++++++++++++--- .../petstoremobile/api/auth/AuthApi.java | 4 ++ .../detailfragments/StaffDetailFragment.java | 37 +++++++++----- .../main/res/layout/fragment_staff_detail.xml | 46 +++++++---------- 4 files changed, 89 insertions(+), 48 deletions(-) diff --git a/android/app/src/main/java/com/example/petstoremobile/activities/ForgotPasswordActivity.java b/android/app/src/main/java/com/example/petstoremobile/activities/ForgotPasswordActivity.java index 385444ed..82ea9934 100644 --- a/android/app/src/main/java/com/example/petstoremobile/activities/ForgotPasswordActivity.java +++ b/android/app/src/main/java/com/example/petstoremobile/activities/ForgotPasswordActivity.java @@ -1,6 +1,7 @@ package com.example.petstoremobile.activities; import android.os.Bundle; +import android.view.View; import android.widget.Toast; import androidx.activity.EdgeToEdge; @@ -9,14 +10,26 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.example.petstoremobile.api.auth.AuthApi; import com.example.petstoremobile.databinding.ActivityForgotPasswordBinding; import com.example.petstoremobile.utils.InputValidator; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; + import dagger.hilt.android.AndroidEntryPoint; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; @AndroidEntryPoint public class ForgotPasswordActivity extends AppCompatActivity { + @Inject + AuthApi authApi; + private ActivityForgotPasswordBinding binding; @Override @@ -33,14 +46,39 @@ public class ForgotPasswordActivity extends AppCompatActivity { }); binding.btnSubmit.setOnClickListener(v -> { - if (InputValidator.isValidEmail(binding.etEmail)) { - String email = binding.etEmail.getText().toString().trim(); - // TODO: Implement password reset logic here - Toast.makeText(this, "If this email is linked, a reset email will be sent.", Toast.LENGTH_LONG).show(); - finish(); - } + if (!InputValidator.isValidEmail(binding.etEmail)) return; + String email = binding.etEmail.getText().toString().trim(); + sendResetLink(email); }); binding.btnBackToLogin.setOnClickListener(v -> finish()); } + + private void sendResetLink(String email) { + binding.btnSubmit.setEnabled(false); + + Map body = new HashMap<>(); + body.put("usernameOrEmail", email); + + authApi.forgotPassword(body).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (binding == null) return; + binding.btnSubmit.setEnabled(true); + Toast.makeText(ForgotPasswordActivity.this, + "If this email is registered, a reset link will be sent.", + Toast.LENGTH_LONG).show(); + finish(); + } + + @Override + public void onFailure(Call call, Throwable t) { + if (binding == null) return; + binding.btnSubmit.setEnabled(true); + Toast.makeText(ForgotPasswordActivity.this, + "Could not send reset link. Please try again.", + Toast.LENGTH_LONG).show(); + } + }); + } } diff --git a/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthApi.java b/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthApi.java index c0d5c1fe..3a2f13e0 100644 --- a/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthApi.java +++ b/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthApi.java @@ -43,4 +43,8 @@ public interface AuthApi { @DELETE("api/v1/auth/me/avatar") Call deleteAvatar(); + //forgot password endpoint + @POST("api/v1/auth/forgot-password") + Call forgotPassword(@Body Map body); + } diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/StaffDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/StaffDetailFragment.java index 94b2b307..9bb3435d 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/StaffDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/StaffDetailFragment.java @@ -28,8 +28,6 @@ public class StaffDetailFragment extends Fragment { private FragmentStaffDetailBinding binding; private StaffDetailViewModel viewModel; - private final String[] ROLES = {"STAFF", "ADMIN"}; - private final String[] STAFF_ROLES = {"STORE_MANAGER", "SALES_ASSOCIATE", "GROOMER", "VETERINARIAN"}; private final String[] STATUSES = {"Active", "Inactive"}; private long preselectedStoreId = -1; @@ -59,8 +57,6 @@ public class StaffDetailFragment extends Fragment { } private void setupSpinners() { - SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerStaffRole, ROLES); - SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerStaffType, STAFF_ROLES); SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerStaffStatus, STATUSES); } @@ -112,8 +108,6 @@ public class StaffDetailFragment extends Fragment { binding.etStaffEmail.setText(e.getEmail()); binding.etStaffPhone.setText(e.getPhone()); - SpinnerUtils.setSelectionByValue(binding.spinnerStaffRole, e.getRole()); - SpinnerUtils.setSelectionByValue(binding.spinnerStaffType, e.getStaffRole()); binding.spinnerStaffStatus.setSelection(Boolean.TRUE.equals(e.getActive()) ? 0 : 1); preselectedStoreId = e.getPrimaryStoreId() != null ? e.getPrimaryStoreId() : -1; @@ -131,17 +125,35 @@ public class StaffDetailFragment extends Fragment { private void save() { if (!InputValidator.isNotEmpty(binding.etStaffUsername, "Username")) return; - + + String password = binding.etStaffPassword.getText().toString().trim(); + String confirmPassword = binding.etStaffConfirmPassword.getText().toString().trim(); + if (!viewModel.isEditing()) { if (!InputValidator.isNotEmpty(binding.etStaffPassword, "Password")) return; - String pass = binding.etStaffPassword.getText().toString(); - if (pass.length() < 6) { + if (password.length() < 6) { binding.etStaffPassword.setError("At least 6 characters"); binding.etStaffPassword.requestFocus(); return; } + if (!password.equals(confirmPassword)) { + binding.etStaffConfirmPassword.setError("Passwords do not match"); + binding.etStaffConfirmPassword.requestFocus(); + return; + } + } else if (!password.isEmpty()) { + if (password.length() < 6) { + binding.etStaffPassword.setError("At least 6 characters"); + binding.etStaffPassword.requestFocus(); + return; + } + if (!password.equals(confirmPassword)) { + binding.etStaffConfirmPassword.setError("Passwords do not match"); + binding.etStaffConfirmPassword.requestFocus(); + return; + } } - + if (!InputValidator.isNotEmpty(binding.etStaffFirstName, "First Name")) return; if (!InputValidator.isNotEmpty(binding.etStaffLastName, "Last Name")) return; if (!InputValidator.isValidEmail(binding.etStaffEmail)) return; @@ -149,13 +161,12 @@ public class StaffDetailFragment extends Fragment { if (!InputValidator.isSpinnerSelected(binding.spinnerStaffStore, "Primary Store")) return; String username = binding.etStaffUsername.getText().toString().trim(); - String password = binding.etStaffPassword.getText().toString().trim(); String firstName = binding.etStaffFirstName.getText().toString().trim(); String lastName = binding.etStaffLastName.getText().toString().trim(); String email = binding.etStaffEmail.getText().toString().trim(); String phone = binding.etStaffPhone.getText().toString().trim(); - String role = ROLES[binding.spinnerStaffRole.getSelectedItemPosition()]; - String staffRole = STAFF_ROLES[binding.spinnerStaffType.getSelectedItemPosition()]; + String role = "STAFF"; + String staffRole = null; boolean active = binding.spinnerStaffStatus.getSelectedItemPosition() == 0; List stores = viewModel.getStoreList().getValue(); diff --git a/android/app/src/main/res/layout/fragment_staff_detail.xml b/android/app/src/main/res/layout/fragment_staff_detail.xml index 8edd2632..a5e0527e 100644 --- a/android/app/src/main/res/layout/fragment_staff_detail.xml +++ b/android/app/src/main/res/layout/fragment_staff_detail.xml @@ -101,6 +101,23 @@ android:inputType="textPassword" android:layout_marginBottom="16dp"/> + + + + + - - - - - - - - -