diff --git a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/AuthApi.java b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/AuthApi.java index 0755ef9e..2a8c3417 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/AuthApi.java +++ b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/AuthApi.java @@ -5,6 +5,8 @@ import org.example.petshopdesktop.api.dto.auth.AvatarUploadResponse; import org.example.petshopdesktop.api.dto.auth.UserInfoResponse; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; public class AuthApi { private static final AuthApi INSTANCE = new AuthApi(); @@ -33,4 +35,10 @@ public class AuthApi { public void deleteAvatar() throws Exception { apiClient.delete("/api/v1/auth/me/avatar"); } + + public void forgotPassword(String usernameOrEmail) throws Exception { + Map body = new HashMap<>(); + body.put("usernameOrEmail", usernameOrEmail); + apiClient.post("/api/v1/auth/forgot-password", body, Object.class); + } } diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/LoginController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/LoginController.java index 70c70e12..6c3427ea 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/LoginController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/LoginController.java @@ -1,12 +1,15 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.PasswordField; +import javafx.scene.control.TextInputDialog; import javafx.scene.control.TextField; import javafx.scene.layout.StackPane; import javafx.stage.Stage; @@ -14,6 +17,7 @@ import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.auth.LoginRequest; import org.example.petshopdesktop.api.dto.auth.LoginResponse; import org.example.petshopdesktop.api.dto.auth.UserInfoResponse; +import org.example.petshopdesktop.api.endpoints.AuthApi; import org.example.petshopdesktop.auth.Role; import org.example.petshopdesktop.auth.UserSession; import org.example.petshopdesktop.ui.SvgWebViewFactory; @@ -105,6 +109,42 @@ public class LoginController { } } + @FXML + void lnkForgotPasswordClicked(ActionEvent event) { + TextInputDialog dialog = new TextInputDialog(); + dialog.setTitle("Forgot Password"); + dialog.setHeaderText("Reset your password"); + dialog.setContentText("Enter your username or email:"); + + dialog.showAndWait().ifPresent(input -> { + if (input.trim().isEmpty()) return; + new Thread(() -> { + try { + AuthApi.getInstance().forgotPassword(input.trim()); + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Reset Link Sent"); + alert.setHeaderText(null); + alert.setContentText("If this account exists, a password reset link has been sent to the associated email."); + alert.showAndWait(); + }); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "LoginController.lnkForgotPasswordClicked", + e, + "Forgot password request for: " + input.trim()); + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Error"); + alert.setHeaderText(null); + alert.setContentText("Could not send reset link. Please try again."); + alert.showAndWait(); + }); + } + }).start(); + }); + } + private void openMainLayout() { try { FXMLLoader loader = new FXMLLoader( diff --git a/desktop/src/main/resources/org/example/petshopdesktop/login-view.fxml b/desktop/src/main/resources/org/example/petshopdesktop/login-view.fxml index 1fe902ed..06b1eae8 100644 --- a/desktop/src/main/resources/org/example/petshopdesktop/login-view.fxml +++ b/desktop/src/main/resources/org/example/petshopdesktop/login-view.fxml @@ -2,6 +2,7 @@ + @@ -83,6 +84,15 @@ + + + + + +