From 9fbdf460e8267e0ed93ecdbd050967eee5049021 Mon Sep 17 00:00:00 2001 From: Asal Lotfi Date: Thu, 4 Sep 2025 15:26:43 +0330 Subject: [PATCH] Change Credentials UI implemented. --- .../UI/ChangeCredentialsController.java | 160 ++++++++++++++++++ .../UI/CheckPasswordController.java | 23 ++- .../telegramfinalproject/CSS/dark_theme.css | 13 +- .../telegramfinalproject/CSS/light_theme.css | 10 ++ .../Fxml/change_credentials.fxml | 82 +++++++++ 5 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java create mode 100644 src/main/resources/org/to/telegramfinalproject/Fxml/change_credentials.fxml diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java new file mode 100644 index 0000000..fd06ad4 --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java @@ -0,0 +1,160 @@ +package org.to.telegramfinalproject.UI; + +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; + +public class ChangeCredentialsController { + + @FXML private VBox credentialsCard; + @FXML private Pane overlayBackground; + @FXML private TextField usernameField; + @FXML private Label usernameLabel; + + @FXML private Label passwordLabel; + @FXML private PasswordField passwordField; + @FXML private TextField visiblePasswordField; + @FXML private Button togglePasswordBtn; + + @FXML private Label confirmPasswordLabel; + @FXML private PasswordField confirmPasswordField; + @FXML private TextField visibleConfirmPasswordField; + @FXML private Button toggleConfirmBtn; + + @FXML private Button cancelButton; + @FXML private Button saveButton; + @FXML private Button closeButton; + + private boolean passwordVisible = false; + private boolean confirmVisible = false; + + @FXML + private void initialize() { + // Toggle password visibility + togglePasswordBtn.setOnAction(e -> togglePasswordVisibility()); + toggleConfirmBtn.setOnAction(e -> toggleConfirmVisibility()); + + saveButton.setOnAction(e -> validateAndSave()); + + // Close the overlay + closeButton.setOnAction(e -> + MainController.getInstance().closeOverlay(credentialsCard.getParent())); + cancelButton.setOnAction(e -> + MainController.getInstance().closeOverlay(credentialsCard.getParent())); + overlayBackground.setOnMouseClicked(e -> + MainController.getInstance().closeOverlay(credentialsCard.getParent()) + ); + + // Reset error when typing + usernameField.textProperty().addListener((obs, o, n) -> removeError(usernameField, usernameLabel)); + + passwordField.textProperty().addListener((obs, o, n) -> { + visiblePasswordField.setText(n); // keep synced + removeError(passwordField, passwordLabel); + removeError(visiblePasswordField, passwordLabel); + }); + visiblePasswordField.textProperty().addListener((obs, o, n) -> { + passwordField.setText(n); + removeError(passwordField, passwordLabel); + removeError(visiblePasswordField, passwordLabel); + }); + + confirmPasswordField.textProperty().addListener((obs, o, n) -> { + visibleConfirmPasswordField.setText(n); + removeError(confirmPasswordField, confirmPasswordLabel); + removeError(visibleConfirmPasswordField, confirmPasswordLabel); + }); + visibleConfirmPasswordField.textProperty().addListener((obs, o, n) -> { + confirmPasswordField.setText(n); + removeError(confirmPasswordField, confirmPasswordLabel); + removeError(visibleConfirmPasswordField, confirmPasswordLabel); + }); + + // Auto_focus password field when overlay opens + Platform.runLater(() -> usernameField.requestFocus()); + } + + private void togglePasswordVisibility() { + passwordVisible = !passwordVisible; + visiblePasswordField.setText(passwordField.getText()); + visiblePasswordField.setVisible(passwordVisible); + visiblePasswordField.setManaged(passwordVisible); + + passwordField.setVisible(!passwordVisible); + passwordField.setManaged(!passwordVisible); + + togglePasswordBtn.setText(passwordVisible ? "👁" : "👁"); + } + + private void toggleConfirmVisibility() { + confirmVisible = !confirmVisible; + visibleConfirmPasswordField.setText(confirmPasswordField.getText()); + visibleConfirmPasswordField.setVisible(confirmVisible); + visibleConfirmPasswordField.setManaged(confirmVisible); + + confirmPasswordField.setVisible(!confirmVisible); + confirmPasswordField.setManaged(!confirmVisible); + + toggleConfirmBtn.setText(confirmVisible ? "👁" : "👁"); + } + + private void validateAndSave() { + boolean hasError = false; + + // --- Username check --- + if (usernameField.getText().trim().isEmpty()) { + addError(usernameField, usernameLabel); + hasError = true; + } else { + removeError(usernameField, usernameLabel); + } + + // --- Password check --- + String pwd = passwordVisible ? visiblePasswordField.getText().trim() : passwordField.getText().trim(); + if (pwd.isEmpty()) { + addError(passwordField, passwordLabel); + addError(visiblePasswordField, passwordLabel); + hasError = true; + } else { + removeError(passwordField, passwordLabel); + removeError(visiblePasswordField, passwordLabel); + } + + // --- Confirm password check --- + String confirm = confirmVisible ? visibleConfirmPasswordField.getText().trim() : confirmPasswordField.getText().trim(); + if (confirm.isEmpty()) { + addError(confirmPasswordField, confirmPasswordLabel); + addError(visibleConfirmPasswordField, confirmPasswordLabel); + hasError = true; + } else if (!confirm.equals(pwd)) { + addError(confirmPasswordField, confirmPasswordLabel); + addError(visibleConfirmPasswordField, confirmPasswordLabel); + hasError = true; + } else { + removeError(confirmPasswordField, confirmPasswordLabel); + removeError(visibleConfirmPasswordField, confirmPasswordLabel); + } + + if (hasError) return; + + // TODO: send to server + System.out.println("Saving new credentials..."); + } + + private void addError(TextField field, Label label) { + if (!field.getStyleClass().contains("error-input")) { + field.getStyleClass().add("error-input"); + } + if (!label.getStyleClass().contains("error-label")) { + label.getStyleClass().add("error-label"); + } + } + + private void removeError(TextField field, Label label) { + field.getStyleClass().remove("error-input"); + label.getStyleClass().remove("error-label"); + } +} diff --git a/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java b/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java index 5b73e4d..b023d71 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java @@ -2,12 +2,16 @@ package org.to.telegramfinalproject.UI; import javafx.application.Platform; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; +import java.io.IOException; + public class CheckPasswordController { @FXML private VBox checkPasswordCard; @@ -103,9 +107,8 @@ public class CheckPasswordController { visiblePasswordField.getStyleClass().remove("error"); passwordLabel.getStyleClass().remove("error"); - // TODO: go to change credentials scene - System.out.println("Password OK → go to next scene"); - // MainController.getInstance().showOverlay("/org/to/telegramfinalproject/Fxml/change_credentials.fxml"); + // Go to the next scene + openChangeCredentials(); } else { // Error → add error styles @@ -142,4 +145,18 @@ public class CheckPasswordController { icon.setFitHeight(16); backButton.setGraphic(icon); } + + private void openChangeCredentials() { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource( + "/org/to/telegramfinalproject/Fxml/change_credentials.fxml")); + Node overlay = loader.load(); + + // Show new overlay + MainController.getInstance().showOverlay(overlay); + + } catch (IOException ex) { + ex.printStackTrace(); + } + } } diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css index 8e75311..967258c 100644 --- a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css +++ b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css @@ -1067,4 +1067,15 @@ .blocked-list .list-cell:hover { -fx-background-color: #2a3a4a; -} \ No newline at end of file +} + +/* Error label */ +.label.error-label { + -fx-text-fill: red; +} + +/* Error input */ +.error-input { + -fx-border-color: red; + -fx-border-radius: 6; +} diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css index bed18c0..9f00b66 100644 --- a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css +++ b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css @@ -1060,3 +1060,13 @@ -fx-background-radius: 4; /* soft rounded edges */ } +/* Error label */ +.label.error-label { + -fx-text-fill: red; +} + +/* Error input */ +.error-input { + -fx-border-color: red; + -fx-border-radius: 6; +} diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/change_credentials.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/change_credentials.fxml new file mode 100644 index 0000000..647de6e --- /dev/null +++ b/src/main/resources/org/to/telegramfinalproject/Fxml/change_credentials.fxml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + +