Skip to content

Commit

Permalink
Merge pull request #73 from Group-5/update/style/javadocAndValidation
Browse files Browse the repository at this point in the history
Merge Update/style/javadocandvalidation into release/v2.0.0
  • Loading branch information
lucych authored Apr 21, 2026
2 parents 2d3df56 + df0905e commit d3b3174
Show file tree
Hide file tree
Showing 35 changed files with 672 additions and 432 deletions.
12 changes: 10 additions & 2 deletions src/main/java/edu/group5/app/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import edu.group5.app.model.user.UserService;
import edu.group5.app.model.wrapper.DbWrapper;
import edu.group5.app.model.wrapper.OrgApiWrapper;
import edu.group5.app.view.aboutuspage.AboutUsView;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
Expand All @@ -35,6 +36,7 @@ public class App extends Application {
NavigationController nav;

private Logger logger;
static int MAX_RETRIES = 3;

@Override
public void init() {
Expand All @@ -44,8 +46,14 @@ public void init() {
this.dbWrapper = new DbWrapper(false);
OrgApiWrapper orgApiWrapper = new OrgApiWrapper("https://app.innsamlingskontrollen.no/api/public/v1/all");

while (!dbWrapper.connect()) {
int retries = 0;
while (!dbWrapper.connect() && retries < MAX_RETRIES) {
this.logger.warning("Failed to connect to database");
retries++;
}
if (retries == MAX_RETRIES) {
this.logger.severe("Failed to connect to database after " + MAX_RETRIES + " attempts");
throw new RuntimeException("Failed to connect to database");
}

// Load data from database
Expand Down Expand Up @@ -75,7 +83,7 @@ public void init() {
OrganizationService organizationService = new OrganizationService(organizationRepository, orgScraper);
this.root = new BorderPane();
this.appState = new AppState();
this.nav = new NavigationController(root, appState, userService, donationService, organizationService);
this.nav = new NavigationController(root, appState, userService, donationService, organizationService, this.getHostServices());
}

@Override
Expand Down
31 changes: 24 additions & 7 deletions src/main/java/edu/group5/app/control/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
import edu.group5.app.model.AppState;
import edu.group5.app.model.user.User;
import edu.group5.app.model.user.UserService;
import edu.group5.app.utils.ParameterValidator;
import edu.group5.app.view.loginpage.LoginPageView;
import edu.group5.app.view.loginpage.SignUpPageView;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;

import java.util.Arrays;

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

/**
Expand All @@ -31,11 +29,31 @@ public class AuthController {
private final UserService userService;

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


/**
* Sets the current logged-in user.
* @param user the user to set as current
*/
public void setCurrentUser(User user) {
appState.setCurrentUser(user);
}

/**
* Gets the current logged-in user.
* @return the current user, or null if no user logged in
*/
public User getCurrentUser() {
return appState.getCurrentUser();
}

/**
* Handles the registration of a {@link User}.
*
Expand Down Expand Up @@ -69,7 +87,7 @@ public void handleSignUp(SignUpPageView view, String firstName, String lastName,
// Clears password char array after creating a hash.
String hashedPassword = encoder.encode(new String(passwordChars));
for (int i = 0; i < passwordChars.length; i++) {
passwordChars[0] = '0';
passwordChars[i] = '\u0000';
}

Alert privacyPolicy = new Alert(Alert.AlertType.CONFIRMATION);
Expand All @@ -86,9 +104,8 @@ public void handleSignUp(SignUpPageView view, String firstName, String lastName,

if (success) {
User user = userService.getUserByEmail(email);

appState.setCurrentUser(user);
nav.showHomePage();
appState.setCurrentUser(user);
nav.showHomePage();
} else {
view.showError("Registration failed. Email may already be in use.");
}
Expand Down
54 changes: 51 additions & 3 deletions src/main/java/edu/group5/app/control/DonationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.group5.app.model.organization.Organization;
import edu.group5.app.model.user.Customer;
import edu.group5.app.model.user.User;
import edu.group5.app.utils.ParameterValidator;

import java.math.BigDecimal;
import java.util.HashSet;
Expand Down Expand Up @@ -34,19 +35,55 @@ public class DonationController {
private final DonationService service;

public DonationController(AppState appState, NavigationController nav, DonationService service) {
ParameterValidator.objectChecker(appState, "AppState");
ParameterValidator.objectChecker(nav, "NavigationController");
ParameterValidator.objectChecker(service, "DonationService");
this.appState = appState;
this.nav = nav;
this.service = service;
}

/**
* Sets the current donation amount.
* @param amount the amount to donate
*/
public void setDonationAmount(BigDecimal amount) {
appState.setCurrentDonationAmount(amount);
}

/**
* Gets the current donation amount.
* @return the donation amount
*/
public BigDecimal getDonationAmount() {
return appState.getCurrentDonationAmount();
}

/**
* Sets the current payment method.
* @param paymentMethod the payment method
*/
public void setPaymentMethod(String paymentMethod) {
appState.setCurrentPaymentMethod(paymentMethod);
}

/**
* Gets the current payment method.
* @return the payment method
*/
public String getPaymentMethod() {
return appState.getCurrentPaymentMethod();
}

/**
* 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);
ParameterValidator.intChecker(userId, "User ID");
return service.getUserDonations(userId);
}

/**
Expand All @@ -56,7 +93,11 @@ public Map<Integer, Donation> getUserDonations(int userId) {
* @return a set of organization IDs
*/
public Set<Integer> getUniqueOrganizationIDs() {
Map<Integer, Donation> userDonations = getUserDonations(appState.getCurrentUser().getUserId());
User currentUser = appState.getCurrentUser();
if (currentUser == null) {
throw new IllegalStateException("No user logged in");
}
Map<Integer, Donation> userDonations = getUserDonations(currentUser.getUserId());

Set<Integer> uniqueOrganizations = new HashSet<>();
for (Donation donation : userDonations.values()) {
Expand Down Expand Up @@ -146,19 +187,26 @@ private void handleDonate() {
);

if (success) {
System.out.println("Donation created: " + amount + " kr to " + currentOrg.name() + ", with payment method: " + paymentMethod);
System.out.println("Donation created: "
+ amount + " kr to " + currentOrg.name()
+ ", with payment method: " + paymentMethod);
} else {
System.err.println("Failed to create donation");
}

// Clear donation session state
appState.setCurrentDonationAmount(null);
// Clear org
appState.setCurrentOrganization(null);
// Clear payment method
appState.setCurrentPaymentMethod(null);

// Navigate to payment complete
nav.showPaymentCompletePage();
}

private void showError(String message) {
ParameterValidator.stringChecker(message, "message");
Alert errorAlert = new Alert(Alert.AlertType.WARNING);
errorAlert.setTitle("Donation Error");
errorAlert.setHeaderText("Cannot Process Donation");
Expand Down
86 changes: 74 additions & 12 deletions src/main/java/edu/group5/app/control/NavigationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import edu.group5.app.model.donation.DonationService;
import edu.group5.app.model.organization.OrganizationService;
import edu.group5.app.model.user.UserService;
import edu.group5.app.utils.ParameterValidator;
import edu.group5.app.view.Header;
import edu.group5.app.view.aboutuspage.AboutUsView;
import edu.group5.app.view.causespage.CausesPageView;
import edu.group5.app.view.donationpage.DonationPageView;
import edu.group5.app.view.donationpage.PaymentCompletePageView;
Expand All @@ -14,75 +16,135 @@
import edu.group5.app.view.loginpage.SignUpPageView;
import edu.group5.app.view.organizationpage.OrganizationPageView;
import edu.group5.app.view.userpage.UserPageView;
import javafx.application.HostServices;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;

/**
* Controller responsible for navigating between views within the root node.
* Controller responsible for handling navigation between different pages of the application.
* Coordinates between {@link AppState}, {@link AuthController}, {@link DonationController},
* {@link OrganizationController} and the various views to manage page transitions and state updates.
* <p>
* Provides methods to navigate to the home page, login page, sign-up page, causes page,
* organization page, donation page, payment complete page and user profile page. Each method updates the
* top header and center content of the main application layout accordingly.
* </p>
*/
public class NavigationController {
private final BorderPane root;
private final Header header;
private final LoginHeader loginHeader;

private final AppState appState;
private final HostServices hostServices;

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

public NavigationController(BorderPane root, AppState appState, UserService userService, DonationService donationService, OrganizationService organizationService) {
public NavigationController(BorderPane root, AppState appState, UserService userService,
DonationService donationService, OrganizationService organizationService, HostServices hostServices) {
ParameterValidator.objectChecker(root, "Root BorderPane");
ParameterValidator.objectChecker(appState, "AppState");
ParameterValidator.objectChecker(userService, "UserService");
ParameterValidator.objectChecker(donationService, "DonationService");
ParameterValidator.objectChecker(organizationService, "OrganizationService");
ParameterValidator.objectChecker(hostServices, "HostServices");

this.root = root;
this.header = new Header(this);
this.loginHeader = new LoginHeader();

this.appState = appState;
this.hostServices = hostServices;

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

/**
* Navigates to the home page by setting the top header and center content of the main layout.
* The home page serves as the landing page of the application, providing an overview and access to various features.
*/
public void showHomePage() {
root.setTop(header);
root.setCenter(new HomePageView(appState, this));
root.setCenter(new HomePageView(this));
}

/**
* Navigates to the login page by setting the top header and center content of the main layout.
* The login page allows existing users to enter their credentials and access their account.
*/
public void showLoginPage() {
root.setTop(loginHeader);
root.setCenter(new LoginPageView(appState, this, authController));
root.setCenter(new LoginPageView(this, authController));
}

/**
* Navigates to the sign-up page by setting the top header and center content of the main layout.
* The sign-up page allows new users to create an account by providing their details.
*/
public void showSignUpPage() {
root.setTop(loginHeader);
root.setCenter(new SignUpPageView(appState, this, authController));
root.setCenter(new SignUpPageView(this, authController));
}

/**
* Navigates to the payment complete page by setting the top header and center content of the main layout.
* The payment complete page confirms the successful completion of a donation transaction.
*/
public void showPaymentCompletePage() {
root.setTop(header);
root.setCenter(new PaymentCompletePageView(this));
}

/**
* Navigates to the causes page by setting the top header and center content of the main layout.
* The causes page allows users to browse and search for organizations they may want to donate to.
*/
public void showCausesPage() {
root.setTop(header);
root.setCenter(new CausesPageView(appState, this, organizationController));
root.setCenter(new CausesPageView(this, organizationController));
}

/**
* Navigates to the organization page by setting the top header and center content of the main layout.
* The organization page provides detailed information about a specific organization, including its mission,
* impact, and donation options, allowing users to learn more before making a donation.
*/
public void showOrganizationPage() {
root.setTop(header);
root.setCenter(new OrganizationPageView(appState, this, donationController));
root.setCenter(new OrganizationPageView(this, organizationController, donationController));
}

/**
* Navigates to the donation page by setting the top header and center content of the main layout.
* The donation page allows users to make new donations to selected organizations.
*/
public void showDonationPage() {
root.setTop(header);
root.setCenter(new DonationPageView(appState, this, donationController));
root.setCenter(new DonationPageView(this, donationController));
}

/**
* Displays an "About Us" dialog with information about the application and its developers.
* The dialog includes a description of the app's mission and a hyperlink to the project's GitHub repository
*/
public void showAboutUsPage() {
root.setTop(header);
new AboutUsView(hostServices).displayAboutUs();
}

/**
* Navigates to the user profile page by setting the top header and center content of the main layout.
* The user profile page allows users to view and manage their account information,
* donation history, and other personalized features.
*/
public void showUserPage() {
root.setTop(header);
root.setCenter(new UserPageView(appState, this, authController, donationController, organizationController));
root.setCenter(new UserPageView(this, authController, donationController, organizationController));
}
}
Loading

0 comments on commit d3b3174

Please sign in to comment.