diff --git a/src/main/java/app/Main.java b/src/main/java/app/Main.java index fea73ff..8c34abd 100644 --- a/src/main/java/app/Main.java +++ b/src/main/java/app/Main.java @@ -10,9 +10,9 @@ import java.math.BigDecimal; import java.sql.SQLException; -import persistence.DonationDao; -import persistence.OrganizationDao; -import persistence.UserDao; +import persistence.dao.DonationDao; +import persistence.dao.OrganizationDao; +import persistence.dao.UserDao; import persistence.db.Database; import javafx.application.Application; import javafx.fxml.FXMLLoader; diff --git a/src/main/java/application/user/UserDonate.java b/src/main/java/application/user/UserDonate.java index bf8f187..bf3889f 100644 --- a/src/main/java/application/user/UserDonate.java +++ b/src/main/java/application/user/UserDonate.java @@ -3,17 +3,29 @@ import domain.donation.Donation; import domain.organization.Organization; import domain.user.User; -import persistence.DonationDao; - +import persistence.dao.DonationDao; import java.math.BigDecimal; +/** + * Use case for handling donations made by a user to an organization. + * Creates a {@link Donation} and persists it to the database. + */ public class UserDonate { private final DonationDao donationDao; + /** + * Creates a new {@code UserDonate} with a default {@link DonationDao}. + */ public UserDonate() { this.donationDao = new DonationDao(); } + /** + * Executes the donation use case by creating and saving a donation. + * @param user the user making the donation + * @param org the organization receiving the donation + * @param amount the donation amount in NOK + */ public void execute(User user, Organization org, BigDecimal amount) { Donation donation = new Donation(amount, user, org); donationDao.insert(donation); diff --git a/src/main/java/application/user/UserRegister.java b/src/main/java/application/user/UserRegister.java index adc2107..0a07316 100644 --- a/src/main/java/application/user/UserRegister.java +++ b/src/main/java/application/user/UserRegister.java @@ -2,7 +2,7 @@ import application.security.PasswordHasher; import domain.user.User; -import persistence.UserRepository; +import persistence.dao.UserRepository; /** * The UserRegister class is responsible for handling the user registration process. @@ -43,7 +43,6 @@ public void execute(String username, String phoneNumber, String password, String email = email.trim().toLowerCase(); phoneNumber = phoneNumber.trim(); - // duplicate check (repo.existsByEmail) if (repo.existsByEmail(email)) { throw new IllegalArgumentException("Email already in use"); } @@ -51,13 +50,9 @@ public void execute(String username, String phoneNumber, String password, String throw new IllegalArgumentException("This username is taken"); } - // hash password (optional) String hashedPassword = hasher.hash(password); - // new User(...) (domain validates) User user = new User(username, phoneNumber, hashedPassword, email); - - // saves user repo.insert(user); } } diff --git a/src/main/java/application/user/UserSignIn.java b/src/main/java/application/user/UserSignIn.java index be6b159..f7ea596 100644 --- a/src/main/java/application/user/UserSignIn.java +++ b/src/main/java/application/user/UserSignIn.java @@ -2,7 +2,7 @@ import application.security.PasswordHasher; import domain.user.User; -import persistence.UserRepository; +import persistence.dao.UserRepository; /** * The UserSignIn class handles the process of user authentication. @@ -36,22 +36,17 @@ public UserSignIn(PasswordHasher hasher, UserRepository repo) { * @return user object, if it exists. */ public User execute(String login, String password) { - // normalize (trim etc.) login.trim().toLowerCase(); User user = repo.findByLogin(login) .orElseThrow(() -> new IllegalArgumentException("Invalid credentials")); - // hash password (optional) String hashedInput = hasher.hash(password); - // compare hashed input with stored hash if (!hashedInput.equals(user.getPassword())) { throw new IllegalArgumentException("Invalid password"); } - System.out.println("Loggin in"); - // return user (if match) return user; } } diff --git a/src/main/java/application/user/UserStatistics.java b/src/main/java/application/user/UserStatistics.java index ed0f2dc..4d3b960 100644 --- a/src/main/java/application/user/UserStatistics.java +++ b/src/main/java/application/user/UserStatistics.java @@ -1,9 +1,9 @@ package application.user; import domain.user.User; -import java.util.ArrayList; + import java.util.List; -import persistence.DonationDao; +import persistence.dao.DonationDao; /** * Provides statistical information about a user's donation activity. @@ -28,8 +28,7 @@ public UserStatistics() { * and its donation count. Returns empty list if the user has no donations. */ public List userFavoriteOrganization(User user) { - List favoriteOrganization = donationDao.getFavoriteOrganization(user.getID()); - return favoriteOrganization; + return donationDao.getFavoriteOrganization(user.getID()); } /** @@ -40,8 +39,7 @@ public List userFavoriteOrganization(User user) { * @return a list of formatted donation strings. Returns empty list if the user has no donations */ public List userDonations(User user) { - List userDonationList = donationDao.getUserDonations(user.getID()); - return userDonationList; + return donationDao.getUserDonations(user.getID()); } /** @@ -51,8 +49,7 @@ public List userDonations(User user) { * @return a string representation of the total donated amount. Returns "0" if no donations exist */ public String userTotalDonationAmount(User user) { - String totalDonations = donationDao.getTotalDonationAmount(user.getID()); - return totalDonations; + return donationDao.getTotalDonationAmount(user.getID()); } /** @@ -62,7 +59,6 @@ public String userTotalDonationAmount(User user) { * @return a string representation of the total number of donations. Returns "0" if none exist. */ public String getTotalDonationsMade(User user) { - String totalDonationsMade = donationDao.getTotalDonationsMade(user.getID()); - return totalDonationsMade; + return donationDao.getTotalDonationsMade(user.getID()); } } diff --git a/src/main/java/domain/donation/Cause.java b/src/main/java/domain/donation/Cause.java deleted file mode 100644 index a69854e..0000000 --- a/src/main/java/domain/donation/Cause.java +++ /dev/null @@ -1,6 +0,0 @@ -package domain.donation; - -/** - * Enum class that contains 5 different cause types - */ -public enum Cause { HEALTH, EMERGENCY_RELIEF, CHILDREN, ENVIRONMENT, CONFLICTS; } diff --git a/src/main/java/domain/donation/Donation.java b/src/main/java/domain/donation/Donation.java index 9835c00..53e1063 100644 --- a/src/main/java/domain/donation/Donation.java +++ b/src/main/java/domain/donation/Donation.java @@ -12,8 +12,7 @@ * Provides set and get methods. */ public class Donation { - private Long id; //get set to null by default, - // Gets set to a value by database when registered? + private Long id; private final BigDecimal amount; private final LocalDateTime dateTime; private final User user; diff --git a/src/main/java/domain/organization/Organization.java b/src/main/java/domain/organization/Organization.java index eaeb838..fd7cec1 100644 --- a/src/main/java/domain/organization/Organization.java +++ b/src/main/java/domain/organization/Organization.java @@ -2,12 +2,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import domain.donation.Cause; -import java.util.Objects; /** - * Class + * Represents a charitable organization retrieved from the Innsamlingskontrollen API. + * Contains basic information such as name, organization number, status and URL. */ @JsonIgnoreProperties(ignoreUnknown = true) public class Organization { @@ -20,27 +19,75 @@ public class Organization { @JsonProperty("status") private String status; - + @JsonProperty("url") private String url; @JsonProperty("is_pre_approved") - private boolean isPreApproved; + public boolean isPreApproved; public Organization() {} + /** + * Returns the organization number. + * @return the organization number + */ public String getOrgNumber() { return orgNumber; } + + /** + * Sets the organization number. + * @param orgNumber the organization number to set + */ public void setOrgNumber(String orgNumber) { this.orgNumber = orgNumber; } + /** + * Returns the name of the organization. + * @return the organization name + */ public String getName() { return name; } + + /** + * Sets the name of the organization. + * @param name the name to set + */ public void setName(String name) { this.name = name; } + /** + * Returns the approval status of the organization. + * @return the status, either "approved" or "obs" + */ public String getStatus() { return status; } + + /** + * Sets the approval status of the organization. + * @param status the status to set + */ public void setStatus(String status) { this.status = status; } + /** + * Returns the URL to the organization's page on Innsamlingskontrollen. + * @return the URL + */ public String getUrl() { return url; } + + /** + * Sets the URL to the organization's page on Innsamlingskontrollen. + * @param url the URL to set + */ public void setUrl(String url) { this.url = url; } - public boolean isPreApproved() { return isPreApproved; } + /** + * Returns whether the organization is pre-approved. + * @return true if pre-approved, false otherwise + */ + public boolean isPreApproved() { + return isPreApproved; + } + + /** + * Sets whether the organization is pre-approved. + * @param preApproved true if pre-approved, false otherwise + */ public void setPreApproved(boolean preApproved) { isPreApproved = preApproved; } + } diff --git a/src/main/java/domain/organization/OrganizationDetails.java b/src/main/java/domain/organization/OrganizationDetails.java index e892e82..a86920a 100644 --- a/src/main/java/domain/organization/OrganizationDetails.java +++ b/src/main/java/domain/organization/OrganizationDetails.java @@ -1,18 +1,35 @@ package domain.organization; +/** + * Holds additional details about an organization fetched from Innsamlingskontrollen's website. + * Contains a short description and a URL to the organization's logo. + */ public class OrganizationDetails { - private String description; - private String logoUrl; + private final String description; + private final String logoUrl; + /** + * Creates a new OrganizationDetails with the given description and logo URL. + * @param description a short description of the organization + * @param logoUrl the URL to the organization's logo + */ public OrganizationDetails(String description, String logoUrl) { this.description = description; this.logoUrl = logoUrl; } + /** + * Returns the organization's description. + * @return the description + */ public String getDescription() { return description; } + /** + * Returns the URL to the organization's logo. + * @return the logo URL + */ public String getLogoUrl() { return logoUrl; } diff --git a/src/main/java/domain/user/Role.java b/src/main/java/domain/user/Role.java deleted file mode 100644 index 673390f..0000000 --- a/src/main/java/domain/user/Role.java +++ /dev/null @@ -1,7 +0,0 @@ -package domain.user; - -/** - * Enum class that defines if a user has the role Admin or user. - */ -public enum Role {ADMIN, USER -} diff --git a/src/main/java/domain/user/User.java b/src/main/java/domain/user/User.java index e5ff5e9..5d471cc 100644 --- a/src/main/java/domain/user/User.java +++ b/src/main/java/domain/user/User.java @@ -12,12 +12,12 @@ public class User { private Long id; /** - * Constructor that takes in the parameters that define a user. - * It contains input validation on all parameters. - * @param userName - * @param phoneNumber - * @param password - * @param eMail + * Creates a new User with the given parameters. + * Validates all input before assigning. + * @param userName the username; must not be null or blank + * @param phoneNumber the phone number; must be exactly 8 digits + * @param password the hashed password + * @param eMail the email address; must be a valid email format */ public User(String userName, String phoneNumber, String password, String eMail) { @@ -87,33 +87,6 @@ public String getPassword() { */ public long getID() { return id; } - /** - * Sets a new password hash for this user. - * - * @param password the new password hash; must not be null - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * Sets a new username for this user. - * - * @param userName the new username; must not be null or blank - */ - public void setUsername(String userName) { - this.userName = userName; - } - - /** - * Sets a new phone number for this user. - * - * @param phoneNumber the new phone number; must be exactly 8 digits - */ - public void setPhonenumber (String phoneNumber) { - this.phoneNumber = phoneNumber; - } - /** * Sets the ID for this user. * @@ -124,9 +97,9 @@ public void setId(Long id) { } /** - * Method that validates that a e-mail is in the right format. - * @param email - * @return + * Validates that an email address is in the correct format. + * @param email the email address to validate + * @return true if the email is valid, false otherwise */ private static boolean isValidEmail(String email) { if (email == null || email.isBlank()) return false; diff --git a/src/main/java/integration/InnsamlingskontrollenClient.java b/src/main/java/integration/InnsamlingskontrollenClient.java index c6083d9..258f2e9 100644 --- a/src/main/java/integration/InnsamlingskontrollenClient.java +++ b/src/main/java/integration/InnsamlingskontrollenClient.java @@ -20,6 +20,11 @@ */ public class InnsamlingskontrollenClient { + /** + * Fetches all organizations from the Innsamlingskontrollen API. + * @return an array of Organization objects + * @throws Exception if the request fails + */ public static Organization[] fetchOrganizations() throws Exception { HttpClient client = HttpClient.newHttpClient(); @@ -35,18 +40,22 @@ public static Organization[] fetchOrganizations() throws Exception { return mapper.readValue(response.body(), Organization[].class); } + /** + * Fetches additional details for an organization from its Innsamlingskontrollen page. + * Scrapes the organization's description and logo URL using Jsoup. + * Returns empty strings if the details cannot be fetched. + * @param url the URL to the organization's page on Innsamlingskontrollen + * @return an OrganizationDetails object containing description and logo URL + */ public static OrganizationDetails fetchDetails(String url) { try { org.jsoup.Connection conn = Jsoup.connect(url); conn.timeout(10000); Document doc = conn.get(); doc.charset(StandardCharsets.UTF_8); - System.out.println(doc.select("section.information").text()); String description = ""; - System.out.println("Section size: " + doc.select("section.information div > p").size()); for (org.jsoup.nodes.Element p : doc.select("section.information div > p")) { - System.out.println("P element: " + p.text()); if (!p.text().isBlank()) { description = p.text(); break; diff --git a/src/main/java/integration/security/Sha256PasswordHasher.java b/src/main/java/integration/security/Sha256PasswordHasher.java index d6c4a4f..95b760c 100644 --- a/src/main/java/integration/security/Sha256PasswordHasher.java +++ b/src/main/java/integration/security/Sha256PasswordHasher.java @@ -12,9 +12,9 @@ public class Sha256PasswordHasher implements PasswordHasher { /** * Method for hashing an inputted password. * Uses the SHA-256 algorithm. - * Transforms the passoword to a UTF-8 byte-array, then digests it using SHA-256. + * Transforms the password to a UTF-8 byte-array, then digests it using SHA-256. * The bytes are then formatted as a 64-character string. - * @param password + * @param password the password to hash * @return a 64-character hash of the password. * @throws RuntimeException if the hashing fails. */ diff --git a/src/main/java/persistence/DonationDao.java b/src/main/java/persistence/dao/DonationDao.java similarity index 99% rename from src/main/java/persistence/DonationDao.java rename to src/main/java/persistence/dao/DonationDao.java index 144ca10..c4893ec 100644 --- a/src/main/java/persistence/DonationDao.java +++ b/src/main/java/persistence/dao/DonationDao.java @@ -1,4 +1,4 @@ -package persistence; +package persistence.dao; import domain.donation.Donation; import domain.organization.Organization; diff --git a/src/main/java/persistence/OrganizationDao.java b/src/main/java/persistence/dao/OrganizationDao.java similarity index 98% rename from src/main/java/persistence/OrganizationDao.java rename to src/main/java/persistence/dao/OrganizationDao.java index 470d74a..cd035e1 100644 --- a/src/main/java/persistence/OrganizationDao.java +++ b/src/main/java/persistence/dao/OrganizationDao.java @@ -1,4 +1,4 @@ -package persistence; +package persistence.dao; import domain.organization.Organization; diff --git a/src/main/java/persistence/UserDao.java b/src/main/java/persistence/dao/UserDao.java similarity index 94% rename from src/main/java/persistence/UserDao.java rename to src/main/java/persistence/dao/UserDao.java index 90a13c4..a1b0544 100644 --- a/src/main/java/persistence/UserDao.java +++ b/src/main/java/persistence/dao/UserDao.java @@ -1,8 +1,9 @@ -package persistence; +package persistence.dao; import java.sql.ResultSet; import java.sql.Statement; import java.util.Optional; + import persistence.db.Database; import java.sql.Connection; import java.sql.PreparedStatement; @@ -48,7 +49,6 @@ public void insert(User user) { } } - //private User mapRow(ResultSet rs) throws SQLException {} /** * Finds a user by their email address. @@ -184,7 +184,7 @@ public boolean existsByUsername(String username) { stmt.setString(1, username.trim().toLowerCase()); try (ResultSet rs = stmt.executeQuery()) { - return rs.next(); // true hvis minst én rad finnes + return rs.next(); } } catch (SQLException e) { @@ -192,13 +192,6 @@ public boolean existsByUsername(String username) { } } - //User findById(long id) throws SQLException {} - - //List findAllUsers() throws SQLException {} - - void update(User user) throws SQLException {} - - void updatePassword(long userId, String newPasswordHash) throws SQLException {} private User mapUser(ResultSet rs) throws SQLException { diff --git a/src/main/java/persistence/UserRepository.java b/src/main/java/persistence/dao/UserRepository.java similarity index 95% rename from src/main/java/persistence/UserRepository.java rename to src/main/java/persistence/dao/UserRepository.java index 9b92669..0ee64c6 100644 --- a/src/main/java/persistence/UserRepository.java +++ b/src/main/java/persistence/dao/UserRepository.java @@ -1,7 +1,6 @@ -package persistence; +package persistence.dao; import domain.user.User; - import java.util.Optional; /** diff --git a/src/main/java/ui/DonationSession.java b/src/main/java/ui/DonationSession.java index 991f91a..0d3bf1d 100644 --- a/src/main/java/ui/DonationSession.java +++ b/src/main/java/ui/DonationSession.java @@ -2,51 +2,46 @@ import domain.organization.Organization; +/** + * Holds the state of an ongoing donation session. + * Passed between donation flow controllers to carry + * the selected organization and amount. + */ public class DonationSession { private Organization organization; private int amount; - private String name; - private String email; - private String phone; + /** + * Returns the organization selected for donation. + * @return the selected organization + */ public Organization getOrganization() { return organization; } + /** + * Returns the donation amount. + * @return the amount in NOK + */ public int getAmount() { return amount; } - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getPhone() { - return phone; - } - + /** + * Sets the organization to donate to. + * @param organization the organization to set + */ public void setOrganization(Organization organization) { this.organization = organization; } + /** + * Sets the donation amount. + * @param amount the amount in NOK + */ public void setAmount(int amount) { this.amount = amount; } - public void setName(String name) { - this.name = name; - } - - public void setEmail(String email) { - this.email = email; - } - - public void setPhone(String phone) { - this.phone = phone; - } } diff --git a/src/main/java/ui/DonationSessionAware.java b/src/main/java/ui/DonationSessionAware.java index 8ceab22..75b9965 100644 --- a/src/main/java/ui/DonationSessionAware.java +++ b/src/main/java/ui/DonationSessionAware.java @@ -1,5 +1,15 @@ package ui; +/** + * Interface for controllers that participate in the donation flow. + * Implementing controllers receive the current {@link DonationSession} + * when they are loaded. + */ public interface DonationSessionAware { + + /** + * Sets the current donation session. + * @param session the active donation session + */ void setDonationSession(DonationSession session); } diff --git a/src/main/java/ui/Page.java b/src/main/java/ui/Page.java index 7dbf0e0..77cac0f 100644 --- a/src/main/java/ui/Page.java +++ b/src/main/java/ui/Page.java @@ -16,14 +16,20 @@ public enum Page { DONATION_PAYMENT("DonationPayment.fxml"), DONATION_CONFIRMATION("DonationConfirmation.fxml"); - - private final String fileName; + /** + * Constructs a Page with the associated FXML filename. + * @param fileName the name of the FXML file for this page + */ Page(String fileName) { this.fileName = fileName; } + /** + * Returns the FXML filename associated with this page. + * @return the FXML filename + */ public String getFileName() { return fileName; } diff --git a/src/main/java/ui/controller/HomeController.java b/src/main/java/ui/controller/HomeController.java index 5d5a217..02420a6 100644 --- a/src/main/java/ui/controller/HomeController.java +++ b/src/main/java/ui/controller/HomeController.java @@ -1,20 +1,20 @@ package ui.controller; -import application.security.PasswordHasher; -import application.user.UserSignIn; -import integration.security.Sha256PasswordHasher; import javafx.fxml.FXML; -import javafx.scene.control.Button; -import persistence.UserDao; import ui.Page; - -import java.io.IOException; import java.util.function.Consumer; +/** + * Controller for the home page. + */ public class HomeController implements NavigationAware { private Consumer onNavigate; + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } diff --git a/src/main/java/ui/controller/MainController.java b/src/main/java/ui/controller/MainController.java index aaa182b..93d83be 100644 --- a/src/main/java/ui/controller/MainController.java +++ b/src/main/java/ui/controller/MainController.java @@ -11,14 +11,17 @@ import javafx.scene.Parent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; -import persistence.UserDao; +import persistence.dao.UserDao; import ui.DonationSession; import ui.Page; import ui.DonationSessionAware; import ui.controller.donation.DonationFlowController; - import java.io.IOException; +/** + * Main controller for the application. + * Manages page navigation, the donation flow, and the organization detail popup. + */ public class MainController { @FXML @@ -55,6 +58,12 @@ public void initialize() { } } + /** + * Loads and displays the given page in the main content area. + * Sets up the appropriate controller callbacks for each page. + * @param page the page to load + * @throws IOException if the FXML file cannot be loaded + */ public void loadPage(Page page) throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/" + page.getFileName())); Parent root = loader.load(); @@ -69,13 +78,6 @@ public void loadPage(Page page) throws IOException { } }); } - if (controller instanceof OrganizationController c) { - c.setOnDonate(org -> { - try { loadDonationPage(org); } - catch (IOException e) { throw new RuntimeException(e); } - }); - - } if (controller instanceof SignInController c) { c.setUserSignIn(new UserSignIn(new Sha256PasswordHasher(), new UserDao())); } @@ -99,10 +101,20 @@ public void loadPage(Page page) throws IOException { navbarController.showNavbar(); } + /** + * Starts the donation flow for the given organization. + * @param org the organization to donate to + * @throws IOException if the FXML file cannot be loaded + */ public void loadDonationPage(Organization org) throws IOException { donationFlowController.start(org); } + /** + * Shows the organization detail popup for the given organization. + * Fetches description and logo from Innsamlingskontrollen and displays them. + * @param org the organization to show details for + */ public void showOrganizationDetail(Organization org) { try { FXMLLoader loader = new FXMLLoader( diff --git a/src/main/java/ui/controller/MyProfileController.java b/src/main/java/ui/controller/MyProfileController.java index 2af08f7..b8dd62c 100644 --- a/src/main/java/ui/controller/MyProfileController.java +++ b/src/main/java/ui/controller/MyProfileController.java @@ -11,12 +11,16 @@ import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; -import persistence.DonationDao; +import persistence.dao.DonationDao; import ui.Page; import util.SessionManager; import java.util.function.Consumer; +/** + * Controller for the user profile page. + * Displays user information, donation statistics and donation history. + */ public class MyProfileController implements NavigationAware { private Consumer onNavigate; @@ -31,6 +35,10 @@ public class MyProfileController implements NavigationAware { @FXML private TableColumn amountColumn; @FXML private TableColumn dateColumn; + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } diff --git a/src/main/java/ui/controller/NavbarController.java b/src/main/java/ui/controller/NavbarController.java index 18a56ea..0be90c5 100644 --- a/src/main/java/ui/controller/NavbarController.java +++ b/src/main/java/ui/controller/NavbarController.java @@ -8,6 +8,10 @@ import ui.Page; import util.SessionManager; +/** + * Controller for the navigation bar. + * Handles navigation between pages and updates the active button state. + */ public class NavbarController { private Consumer onNavigate; @@ -20,10 +24,18 @@ public class NavbarController { @FXML private Button signInBtn; + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } + /** + * Highlights the navbar button corresponding to the given page. + * @param page the currently active page + */ public void setActivePage(Page page) { homeBtn.getStyleClass().remove("nav-button-active"); orgBtn.getStyleClass().remove("nav-button-active"); @@ -41,10 +53,16 @@ public void setActivePage(Page page) { } } + /** + * Navigates to the home page. + */ public void goHome() { onNavigate.accept(Page.HOME); } + /** + * Navigates to the sign in page or profile page depending on authentication state. + */ public void goToSignIn() { if (SessionManager.isSignedIn()) { onNavigate.accept(Page.PROFILE); @@ -53,11 +71,17 @@ public void goToSignIn() { } } + /** + * Navigates to the organizations page. + */ public void goToOrganizations() { onNavigate.accept(Page.ORGANIZATIONS); } - + /** + * Updates the sign in button text based on the user's authentication state. + * Shows "My Profile" if signed in, "Sign In" otherwise. + */ public void updateAuthButton() { if (SessionManager.isSignedIn()) { signInBtn.setText("My Profile"); @@ -66,17 +90,17 @@ public void updateAuthButton() { } } - public void clearActivePage() { - homeBtn.getStyleClass().remove("nav-button-active"); - orgBtn.getStyleClass().remove("nav-button-active"); - signInBtn.getStyleClass().remove("nav-button-active"); - } - + /** + * Hides the navbar. + */ public void hideNavbar() { navBar.setVisible(false); navBar.setManaged(false); } + /** + * Shows the navbar. + */ public void showNavbar() { navBar.setVisible(true); navBar.setManaged(true); diff --git a/src/main/java/ui/controller/OrganizationController.java b/src/main/java/ui/controller/OrganizationController.java index ede0dd3..00ad56c 100644 --- a/src/main/java/ui/controller/OrganizationController.java +++ b/src/main/java/ui/controller/OrganizationController.java @@ -8,7 +8,7 @@ import javafx.scene.control.TextField; import javafx.scene.layout.FlowPane; import javafx.scene.layout.VBox; -import persistence.OrganizationDao; +import persistence.dao.OrganizationDao; import ui.Page; import java.sql.SQLException; @@ -17,6 +17,10 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +/** + * Controller for the organizations page. + * Displays a paginated list of approved organizations with search functionality. + */ public class OrganizationController implements NavigationAware{ @FXML @@ -39,15 +43,26 @@ public class OrganizationController implements NavigationAware{ private Consumer onDonate; private Consumer onShowDetail; - + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } + /** + * Sets the callback to invoke when the user clicks Donate on an organization card. + * @param onDonate the callback with the selected organization + */ public void setOnDonate(Consumer onDonate) { this.onDonate = onDonate; } + /** + * Sets the callback to invoke when the user clicks on an organization card. + * @param onShowDetail the callback with the selected organization + */ public void setOnShowDetail(Consumer onShowDetail) { this.onShowDetail = onShowDetail; } @@ -58,7 +73,6 @@ public void initialize() { allOrgs = dao.getAll().stream() .filter(org -> "approved".equals(org.getStatus())) .collect(Collectors.toList()); - System.out.println("Fetched: " + allOrgs.size() + " organizations"); filtrertOrgs = new ArrayList<>(allOrgs); showPage(); @@ -143,5 +157,4 @@ private void nextPage() { page++; showPage(); } - } diff --git a/src/main/java/ui/controller/OrganizationDetailController.java b/src/main/java/ui/controller/OrganizationDetailController.java index 96a8b74..0775ea0 100644 --- a/src/main/java/ui/controller/OrganizationDetailController.java +++ b/src/main/java/ui/controller/OrganizationDetailController.java @@ -3,17 +3,18 @@ import domain.organization.Organization; import domain.organization.OrganizationDetails; import javafx.fxml.FXML; -import javafx.scene.control.Button; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import ui.Page; - import java.awt.Desktop; import java.net.URI; import java.util.function.Consumer; +/** + * Controller for the organization detail popup. + * Displays organization name, verified status, description and logo. + */ public class OrganizationDetailController { @FXML private Label nameLabel; @@ -28,6 +29,12 @@ public class OrganizationDetailController { private Consumer onDonate; private Runnable onClose; + /** + * Sets the organization and its details, and updates all UI elements. + * Cuts the description at 300 characters if it is too long. + * @param org the organization to display + * @param details the scraped details including description and logo URL + */ public void setOrganization(Organization org, OrganizationDetails details) { this.organization = org; nameLabel.setText(org.getName()); @@ -68,10 +75,18 @@ public void setOrganization(Organization org, OrganizationDetails details) { } } + /** + * Sets the callback to invoke when the user clicks Donate. + * @param onDonate the callback with the selected organization + */ public void setOnDonate(Consumer onDonate) { this.onDonate = onDonate; } + /** + * Sets the callback to invoke when the user closes the popup. + * @param onClose the callback to run on close + */ public void setOnClose(Runnable onClose) { this.onClose = onClose; } diff --git a/src/main/java/ui/controller/RegisterController.java b/src/main/java/ui/controller/RegisterController.java index a43a47d..db662f8 100644 --- a/src/main/java/ui/controller/RegisterController.java +++ b/src/main/java/ui/controller/RegisterController.java @@ -9,22 +9,40 @@ import java.util.function.Consumer; +/** + * Controller for the register page. + * Handles user input validation and registration. + */ public class RegisterController implements NavigationAware { - @FXML private TextField usernameField; - @FXML private TextField emailField; - @FXML private TextField phoneNumberField; - @FXML private PasswordField passwordField; - @FXML private PasswordField confirmPasswordField; - @FXML private Label errorLabel; + @FXML + private TextField usernameField; + @FXML + private TextField emailField; + @FXML + private TextField phoneNumberField; + @FXML + private PasswordField passwordField; + @FXML + private PasswordField confirmPasswordField; + @FXML + private Label errorLabel; private UserRegister userRegister; private Consumer onNavigate; + /** + * Sets the user register use case. + * @param userRegister the use case for registering a new user + */ public void setUserRegister(UserRegister userRegister) { this.userRegister = userRegister; } + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } @@ -61,9 +79,4 @@ private void handleRegister() { private void handleSignIn() { onNavigate.accept(Page.SIGN_IN); } - - @FXML - private void handleGoHome() { - onNavigate.accept(Page.HOME); - } } diff --git a/src/main/java/ui/controller/SignInController.java b/src/main/java/ui/controller/SignInController.java index 6541460..6cde88c 100644 --- a/src/main/java/ui/controller/SignInController.java +++ b/src/main/java/ui/controller/SignInController.java @@ -1,26 +1,20 @@ package ui.controller; -import application.security.PasswordHasher; -import application.user.UserRegister; import application.user.UserSignIn; import domain.user.User; -import integration.security.Sha256PasswordHasher; -import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.scene.Node; -import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; -import javafx.stage.Stage; -import persistence.UserDao; import ui.Page; import util.SessionManager; - import java.io.IOException; import java.util.function.Consumer; +/** + * Controller for the sign-in page. + * Handles user authentication and navigation after sign in. + */ public class SignInController implements NavigationAware { @FXML private TextField loginField; @@ -30,17 +24,24 @@ public class SignInController implements NavigationAware { private UserSignIn userSignIn; private Consumer onNavigate; + /** + * Sets the sign in use case. + * @param userSignIn the use case for signing in a user + */ public void setUserSignIn(UserSignIn userSignIn) { this.userSignIn = userSignIn; } + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } @FXML private void handleSignIn() { - String login = loginField.getText().trim(); String password = passwordField.getText().trim(); @@ -49,7 +50,6 @@ private void handleSignIn() { return; } - // nullstill eventuell gammel feilmelding errorLabel.setText(""); try { diff --git a/src/main/java/ui/controller/donation/DonationAmountController.java b/src/main/java/ui/controller/donation/DonationAmountController.java index 064c07d..2b35c83 100644 --- a/src/main/java/ui/controller/donation/DonationAmountController.java +++ b/src/main/java/ui/controller/donation/DonationAmountController.java @@ -9,6 +9,10 @@ import java.util.function.Consumer; +/** + * Controller for the donation amount selection page. + * Handles amount input validation and navigation in the donation flow. + */ public class DonationAmountController implements DonationSessionAware { @FXML private Label orgLabel; @@ -19,20 +23,35 @@ public class DonationAmountController implements DonationSessionAware { private Consumer onContinue; private Runnable onBack; + /** + * Sets the current donation session and updates the organization label. + * @param donationSession the active donation session + */ @Override public void setDonationSession(DonationSession donationSession) { this.donationSession = donationSession; orgLabel.setText("Donating to: " + donationSession.getOrganization().getName()); } + /** + * Sets the callback to invoke when the user continues to the next step. + * @param onContinue the callback with the updated donation session + */ public void setOnContinue(Consumer onContinue) { this.onContinue = onContinue; } + /** + * Sets the callback to invoke when the user navigates back. + * @param onBack the callback to run on back navigation + */ public void setOnBack(Runnable onBack) { this.onBack = onBack; } + /** + * Validates the entered amount and continues to the next step in the donation flow. + */ @FXML public void handleContinue() { if (amountField.getText().isBlank()) { diff --git a/src/main/java/ui/controller/donation/DonationConfirmationController.java b/src/main/java/ui/controller/donation/DonationConfirmationController.java index 7fe397c..5e2df03 100644 --- a/src/main/java/ui/controller/donation/DonationConfirmationController.java +++ b/src/main/java/ui/controller/donation/DonationConfirmationController.java @@ -8,7 +8,10 @@ import ui.controller.NavigationAware; import java.util.function.Consumer; - +/** + * Controller for the donation confirmation page. + * Displays the organization name and donation amount after a successful donation. + */ public class DonationConfirmationController implements NavigationAware, DonationSessionAware { @FXML private Label orgLabel; @@ -17,11 +20,19 @@ public class DonationConfirmationController implements NavigationAware, Donation private Consumer onNavigate; private DonationSession donationSession; + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ @Override public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } + /** + * Sets the donation session and updates the confirmation labels. + * @param session the completed donation session + */ @Override public void setDonationSession(DonationSession session) { this.donationSession = session; diff --git a/src/main/java/ui/controller/donation/DonationFlowController.java b/src/main/java/ui/controller/donation/DonationFlowController.java index f9d014a..6b70027 100644 --- a/src/main/java/ui/controller/donation/DonationFlowController.java +++ b/src/main/java/ui/controller/donation/DonationFlowController.java @@ -14,6 +14,10 @@ import java.math.BigDecimal; import java.util.function.Consumer; +/** + * Manages the multi-step donation flow. + * Handles navigation between donation steps and hides the navbar during the flow. + */ public class DonationFlowController { private final BorderPane mainPane; private final NavbarController navbarController; @@ -21,11 +25,22 @@ public class DonationFlowController { private Consumer onNavigate; private final UserDonate userDonate = new UserDonate(); + /** + * Creates a new DonationFlowController. + * @param mainPane the main BorderPane to load donation steps into + * @param navbarController the navbar controller used to hide/show the navbar + */ public DonationFlowController(BorderPane mainPane, NavbarController navbarController) { this.mainPane = mainPane; this.navbarController = navbarController; } + /** + * Starts the donation flow for the given organization. + * Navigates to the amount step if signed in, otherwise to the not logged in step. + * @param org the organization to donate to + * @throws IOException if an FXML file cannot be loaded + */ public void start(Organization org) throws IOException { session = new DonationSession(); session.setOrganization(org); @@ -38,6 +53,7 @@ public void start(Organization org) throws IOException { } } + // Loads the "not logged in" page private void loadStep1() throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/DonationNotLoggedIn.fxml")); Parent root = loader.load(); @@ -48,6 +64,8 @@ private void loadStep1() throws IOException { controller.setOnNavigate(onNavigate); mainPane.setCenter(root); } + + // Loads the amount selection page private void loadStep2() throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/DonationAmount.fxml")); Parent root = loader.load(); @@ -72,6 +90,7 @@ private void loadStep2() throws IOException { mainPane.setCenter(root); } + // Loads the payment information page private void loadStep3() throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/DonationPayment.fxml")); Parent root = loader.load(); @@ -101,6 +120,8 @@ private void loadStep3() throws IOException { mainPane.setCenter(root); } + + // Loads the confirmation page private void loadStep4() throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/DonationConfirmation.fxml")); Parent root = loader.load(); @@ -113,6 +134,10 @@ private void loadStep4() throws IOException { mainPane.setCenter(root); } + /** + * Sets the callback for navigating to a page after the donation flow ends. + * @param onNavigate the navigation callback + */ public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } diff --git a/src/main/java/ui/controller/donation/DonationNotLoggedInController.java b/src/main/java/ui/controller/donation/DonationNotLoggedInController.java index fa21d72..fcfe421 100644 --- a/src/main/java/ui/controller/donation/DonationNotLoggedInController.java +++ b/src/main/java/ui/controller/donation/DonationNotLoggedInController.java @@ -1,6 +1,6 @@ package ui.controller.donation; -import domain.organization.Organization; + import javafx.fxml.FXML; import javafx.scene.control.Label; import ui.DonationSession; @@ -10,6 +10,10 @@ import java.util.function.Consumer; +/** + * Controller for the "not logged in" page in the donation flow. + * Shown when a user tries to donate without being signed in. + */ public class DonationNotLoggedInController implements NavigationAware, DonationSessionAware { @FXML private Label orgLabel; @@ -17,12 +21,19 @@ public class DonationNotLoggedInController implements NavigationAware, DonationS private Consumer onNavigate; private DonationSession donationSession; - + /** + * Sets the navigation callback. + * @param onNavigate the callback for navigating to a page + */ @Override public void setOnNavigate(Consumer onNavigate) { this.onNavigate = onNavigate; } + /** + * Sets the donation session and updates the organization label. + * @param session the active donation session + */ @Override public void setDonationSession(DonationSession session) { this.donationSession = session; @@ -40,6 +51,5 @@ public void goToRegister() { public void handleBack() { onNavigate.accept(Page.ORGANIZATIONS); } - } diff --git a/src/main/java/ui/controller/donation/DonationPaymentController.java b/src/main/java/ui/controller/donation/DonationPaymentController.java index ece65d7..5c44b7c 100644 --- a/src/main/java/ui/controller/donation/DonationPaymentController.java +++ b/src/main/java/ui/controller/donation/DonationPaymentController.java @@ -5,9 +5,12 @@ import javafx.scene.control.TextField; import ui.DonationSession; import ui.DonationSessionAware; - import java.util.function.Consumer; +/** + * Controller for the payment information page in the donation flow. + * Handles validation of card number, expiry date and CVC. + */ public class DonationPaymentController implements DonationSessionAware { @FXML private Label orgLabel; @@ -21,6 +24,10 @@ public class DonationPaymentController implements DonationSessionAware { private Consumer onContinue; private Runnable onBack; + /** + * Sets the donation session and updates the organization and amount labels. + * @param donationSession the active donation session + */ @Override public void setDonationSession(DonationSession donationSession) { this.donationSession = donationSession; @@ -28,10 +35,18 @@ public void setDonationSession(DonationSession donationSession) { amountLabel.setText("Amount: " + donationSession.getAmount() + " kr"); } + /** + * Sets the callback to invoke when the user confirms the donation. + * @param onContinue the callback with the updated donation session + */ public void setOnContinue(Consumer onContinue) { this.onContinue = onContinue; } + + /** + * Validates payment information and continues to the confirmation step. + */ @FXML public void handleConfirmDonation() { String cardNumber = cardNumberField.getText().trim().replace(" ", ""); @@ -53,6 +68,10 @@ public void handleConfirmDonation() { onContinue.accept(donationSession); } + /** + * Sets the callback to invoke when the user navigates back. + * @param onBack the callback to run on back navigation + */ public void setOnBack(Runnable onBack) { this.onBack = onBack; } diff --git a/src/main/java/util/SessionManager.java b/src/main/java/util/SessionManager.java index e2a6d4f..3e40ea2 100644 --- a/src/main/java/util/SessionManager.java +++ b/src/main/java/util/SessionManager.java @@ -14,7 +14,7 @@ public class SessionManager { /** * Signs in a user. * Stores the user as the current session holder. - * @param the user tom sign in. + * @param user the user to sign in */ public static void signIn(User user) { SignedIn = true;