Skip to content

Docs/javadoc control #64

Merged
merged 3 commits into from
Apr 16, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,48 @@

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class LoginController {
/**
* Controller responsible for authentication-related operations.
*
* <p>Coordinates between {@link AppState}, {@link NavigationController}
* and {@link UserService} to:
* <ul>
* <li>Sign-up a new user</li>
* <li>Login in a user</li>
* <li>Logout a user</li>
* </ul>
* </p>
*/
public class AuthController {
private final AppState appState;
private final NavigationController nav;
private final UserService userService;

public LoginController(AppState appState, NavigationController nav, UserService userService) {
public AuthController(AppState appState, NavigationController nav, UserService userService) {
this.appState = appState;
this.nav = nav;
this.userService = userService;
}

/**
* Handles the registration of a {@link User}.
*
* <ul>
* <li>Validates the firstname, lastname, email and password fields</li>
* <li>Encrypts the password</li>
* <li>Invokes {@link UserService#registerUser(String, String, String, String, String)} to register the user</li>
* </ul>
*
* <p>If the registration is successful, the user is stored in {@link AppState} and
* the application navigates to the home page. Otherwise, an error message
* is displayed in the provided view.</p>
*
* @param view the view used to display feedback to the user
* @param firstName the user's first name
* @param lastName the user's last name
* @param email the user's email
* @param passwordChars the user's password
*/
public void handleSignUp(SignUpPageView view, String firstName, String lastName, String email, char[] passwordChars) {
if (firstName == null || firstName.trim().isEmpty() ||
lastName == null || lastName.trim().isEmpty() ||
Expand Down Expand Up @@ -56,17 +87,30 @@ public void handleSignUp(SignUpPageView view, String firstName, String lastName,
if (success) {
User user = userService.getUserByEmail(email);

appState.setCurrentUser(user);
nav.showHomePage();
} else {
view.showError("Registration failed. Email may already be in use.");
}
appState.setCurrentUser(user);
nav.showHomePage();
} else {
view.showError("Registration failed. Must Accept Privacy Policy to create account.");
view.showError("Registration failed. Email may already be in use.");
}

}
}

/**
* Handles the login of a {@link User}.
*
* <ul>
* <li>Validates the email and password of the user</li>
* <li>Invokes {@link UserService#login(String, char[])} to login in the user</li>
* </ul>
*
* If the login is successful, the user is stored in {@link AppState} and the
* application navigates to the home page. Otherwise, an error message is
* displayed within the provided view.
*
* @param view the view used to display feedback to the user
* @param email the user's email
* @param passwordChars the user's password
*/
public void handleLogin(LoginPageView view, String email, char[] passwordChars) {
if (email == null || email.trim().isEmpty() || passwordChars == null || passwordChars.length == 0) {
view.showError("Email and password are required");
Expand All @@ -83,10 +127,17 @@ public void handleLogin(LoginPageView view, String email, char[] passwordChars)
}
}

/**
* Handles the logout of a {@link User}.
*
* <p>Clears states in {@link AppState} and the application
* navigates to the login page.</p>
*/
public void handleLogout() {
appState.setCurrentUser(null);
appState.setCurrentOrganization(null);
appState.setCurrentDonationAmount(null);
appState.setCurrentPaymentMethod(null);
nav.showLoginPage();
}
}
}
45 changes: 41 additions & 4 deletions src/main/java/edu/group5/app/control/DonationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;

/**
* Controller responsible for donation-related operations.
*
* <p>
* Coordinates between {@link AppState}, {@link DonationService}
* and {@link NavigationController} to:
* <ul>
* <li>Retrieve donation data for the current user</li>
* <li>Process new donations</li>
* <li>Handle navigation after donation completion</li>
* </ul>
* </p>
*/
public class DonationController {
private final AppState appState;
private final NavigationController nav;
Expand All @@ -26,21 +39,45 @@ public DonationController(AppState appState, NavigationController nav, DonationS
this.service = service;
}

/**
* Retrieves all donations made by a specific user.
*
* @param userId the ID of the user
* @return a map of donations.
*/
public Map<Integer, Donation> getUserDonations(int userId) {
return service.getDonationRepository().filterByUser(userId);
}

public Set<Integer> getUniqueOrgs() {
/**
* Returns a set of unique organization IDs that the current user
* has donated to.
*
* @return a set of organization IDs
*/
public Set<Integer> getUniqueOrganizationIDs() {
Map<Integer, Donation> userDonations = getUserDonations(appState.getCurrentUser().getUserId());

Set<Integer> uniqueOrgs = new HashSet<>();
Set<Integer> uniqueOrganizations = new HashSet<>();
for (Donation donation : userDonations.values()) {
uniqueOrgs.add(donation.organizationId());
uniqueOrganizations.add(donation.organizationId());
}

return uniqueOrgs;
return uniqueOrganizations;
}

/**
* Processes a donation using data stored in {@link AppState}.
*
* <p>
* <ul>
* <li>Validates the current user, organization, amount and payment method</li>
* <li>Invokes {@link DonationService#donate(Customer, int, BigDecimal, String)} to create the donation</li>
* <li>Clears temporary donation state</li>
* <li>Navigates to the payment complete view</li>
* </ul>
* </p>
*/
public void requestDonationConfirmation() {
// Get session data
User currentUser = appState.getCurrentUser();
Expand Down
15 changes: 9 additions & 6 deletions src/main/java/edu/group5/app/control/NavigationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
import edu.group5.app.view.userpage.UserPageView;
import javafx.scene.layout.BorderPane;

/**
* Controller responsible for navigating between views within the root node.
*/
public class NavigationController {
private final BorderPane root;
private final Header header;
private final LoginHeader loginHeader;

private final AppState appState;

private final LoginController loginController;
private final AuthController authController;
private final DonationController donationController;
private final OrganizationController organizationController;

Expand All @@ -34,9 +37,9 @@ public NavigationController(BorderPane root, AppState appState, UserService user

this.appState = appState;

this.loginController = new LoginController(appState, this, userService);
this.authController = new AuthController(appState, this, userService);
this.donationController = new DonationController(appState, this, donationService);
this.organizationController = new OrganizationController(appState, this, organizationService);
this.organizationController = new OrganizationController(organizationService);
}

public void showHomePage() {
Expand All @@ -46,12 +49,12 @@ public void showHomePage() {

public void showLoginPage() {
root.setTop(loginHeader);
root.setCenter(new LoginPageView(appState, this, loginController));
root.setCenter(new LoginPageView(appState, this, authController));
}

public void showSignUpPage() {
root.setTop(loginHeader);
root.setCenter(new SignUpPageView(appState, this, loginController));
root.setCenter(new SignUpPageView(appState, this, authController));
}

public void showPaymentCompletePage() {
Expand Down Expand Up @@ -80,6 +83,6 @@ public void showAboutUsPage() {

public void showUserPage() {
root.setTop(header);
root.setCenter(new UserPageView(appState, this, loginController, donationController, organizationController));
root.setCenter(new UserPageView(appState, this, authController, donationController, organizationController));
}
}
14 changes: 6 additions & 8 deletions src/main/java/edu/group5/app/control/OrganizationController.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
package edu.group5.app.control;

import edu.group5.app.model.AppState;
import edu.group5.app.model.organization.Organization;
import edu.group5.app.model.organization.OrganizationService;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
* Controller responsible for organization-related operations.
*/
public class OrganizationController {
private final AppState appState;
private final NavigationController nav;
private final OrganizationService service;

public OrganizationController(AppState appState, NavigationController nav, OrganizationService service) {
this.appState = appState;
this.nav = nav;
public OrganizationController(OrganizationService service) {
this.service = service;
}

public Organization getOrgById(int orgId) {
public Organization getOrganizationById(int orgId) {
return service.findByOrgNumber(orgId);
}

public Map<Integer, Organization> getTrustedOrgs() {
public Map<Integer, Organization> getTrustedOrganizations() {
return service.getTrustedOrganizations();
}

Expand Down
19 changes: 18 additions & 1 deletion src/main/java/edu/group5/app/view/causespage/CausesPageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private BorderPane createBody() {
vBox.setMaxWidth(Double.MAX_VALUE);

// Load organizations INSTANTLY from cache
allOrganizations = orgController.getTrustedOrgs();
allOrganizations = orgController.getTrustedOrganizations();

vBox.getChildren().add(createOrganizationSection(null));
body.setContent(vBox);
Expand Down Expand Up @@ -126,6 +126,23 @@ private GridPane createOrganizationSection(String searchTerm) {
organizationGrid = grid;
}

if (allOrganizations == null) {
allOrganizations = orgController.getTrustedOrganizations();

//Show loading text while organizations and logos are fetched
grid.add(new javafx.scene.control.Label("Loading..."), 0, 0);

//Fetch trusted organizations with logos asynchronously (runs in background)
orgController.getOrganizationsWithLogosAsync()
.thenAccept(orgs -> {
this.allOrganizations = orgs;

// Update UI when data is ready
Platform.runLater(() -> updateOrganizationGrid(""));
});
return grid;
}

Map<Integer, Organization> organizations = new HashMap<>();
if (searchTerm != null && !searchTerm.isEmpty()) {
// Filter organizations by search term
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/edu/group5/app/view/loginpage/LoginPageView.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package edu.group5.app.view.loginpage;

import edu.group5.app.control.NavigationController;
import edu.group5.app.control.LoginController;
import edu.group5.app.control.AuthController;
import edu.group5.app.model.AppState;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
Expand All @@ -23,16 +23,16 @@
public class LoginPageView extends BorderPane {
private final AppState appState;
private final NavigationController nav;
private final LoginController loginController;
private final AuthController authController;

private TextField emailField;
private PasswordField passwordField;
private Label errorLabel;

public LoginPageView(AppState appState, NavigationController nav, LoginController loginController) {
public LoginPageView(AppState appState, NavigationController nav, AuthController authController) {
this.appState = appState;
this.nav = nav;
this.loginController = loginController;
this.authController = authController;

HBox content = new HBox();
content.setFillHeight(true);
Expand Down Expand Up @@ -105,7 +105,7 @@ private Button getLoginBtn() {
Button loginBtn = new Button("Log In");
loginBtn.setMaxWidth(300);
loginBtn.setId("login-btn");
loginBtn.setOnMouseClicked(e -> loginController.handleLogin(
loginBtn.setOnMouseClicked(e -> authController.handleLogin(
this,
getEmail(),
getPassword()
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/edu/group5/app/view/loginpage/SignUpPageView.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package edu.group5.app.view.loginpage;

import edu.group5.app.control.NavigationController;
import edu.group5.app.control.LoginController;
import edu.group5.app.control.AuthController;
import edu.group5.app.model.AppState;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
Expand All @@ -24,18 +24,18 @@
public class SignUpPageView extends BorderPane {
private final AppState appState;
private final NavigationController nav;
private final LoginController loginController;
private final AuthController authController;

private TextField nameField;
private TextField surnameField;
private TextField emailField;
private PasswordField passwordField;
private Label errorLabel;

public SignUpPageView(AppState appState, NavigationController nav, LoginController loginController) {
public SignUpPageView(AppState appState, NavigationController nav, AuthController authController) {
this.appState = appState;
this.nav = nav;
this.loginController = loginController;
this.authController = authController;

HBox content = new HBox();
content.setFillHeight(true);
Expand Down Expand Up @@ -138,7 +138,7 @@ private Button getSignUpBtn() {
Button signUpBtn = new Button("Sign Up");
signUpBtn.setMaxWidth(300);
signUpBtn.setId("login-btn");
signUpBtn.setOnMouseClicked(e -> loginController.handleSignUp(
signUpBtn.setOnMouseClicked(e -> authController.handleSignUp(
this,
getFirstName(),
getLastName(),
Expand Down
Loading
Loading