diff --git a/docs/SqlDatabase/ER-DiagramFile.mwb b/docs/SqlDatabase/ER-DiagramFile.mwb index c43ee85..5105a8b 100644 Binary files a/docs/SqlDatabase/ER-DiagramFile.mwb and b/docs/SqlDatabase/ER-DiagramFile.mwb differ diff --git a/docs/SqlDatabase/ER-DiagramFile.mwb.bak b/docs/SqlDatabase/ER-DiagramFile.mwb.bak index c348da3..eb0ba08 100644 Binary files a/docs/SqlDatabase/ER-DiagramFile.mwb.bak and b/docs/SqlDatabase/ER-DiagramFile.mwb.bak differ diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java index 1086853..1026c20 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java @@ -6,21 +6,35 @@ import java.util.Objects; import javafx.application.Application; import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.database.DAO.UserDAO; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.database.DatabaseSetup; +import ntnu.systemutvikling.team6.database.Readers.UserSelect; +import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.scraper.FullCharityScrape; import ntnu.systemutvikling.team6.service.APIToDatabaseService; +import ntnu.systemutvikling.team6.service.AuthenticationService; public class HmHApplication extends Application { @Override public void start(Stage stage) throws Exception { + DatabaseConnection conn = new DatabaseConnection(); + AuthenticationService authToken = new AuthenticationService(new UserSelect(conn), new UserDAO(conn)); + FXMLLoader fxmlLoader = new FXMLLoader(HmHApplication.class.getResource("/fxml/frontPage.fxml")); Scene scene = new Scene(fxmlLoader.load()); + + + BaseController controller = fxmlLoader.getController(); + controller.setAuthToken(authToken); + Image icon = new Image( Objects.requireNonNull(HmHApplication.class.getResource("/images/Logo.png")) @@ -72,6 +86,8 @@ public void init() { e.printStackTrace(); } System.out.println("-- \n Init complete \n --"); + + } public static void main(String[] args) { diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AboutPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AboutPageController.java new file mode 100644 index 0000000..46366db --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AboutPageController.java @@ -0,0 +1,17 @@ +package ntnu.systemutvikling.team6.controller; + +import javafx.fxml.FXML; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.FooterController; +import ntnu.systemutvikling.team6.controller.components.NavbarController; + +public class AboutPageController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + + @Override + protected void authTokenisSet() { + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java index e36472d..5a9386e 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java @@ -9,10 +9,7 @@ import javafx.scene.Parent; import javafx.scene.control.TextField; import javafx.scene.layout.FlowPane; -import ntnu.systemutvikling.team6.controller.components.BaseController; -import ntnu.systemutvikling.team6.controller.components.LoaderScene; -import ntnu.systemutvikling.team6.controller.components.NavbarFooterController; -import ntnu.systemutvikling.team6.controller.components.OrganizationCardController; +import ntnu.systemutvikling.team6.controller.components.*; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.database.Readers.CharitySelect; import ntnu.systemutvikling.team6.models.Charity; @@ -26,15 +23,22 @@ * on the featured charity to see more details about it. The user can also switch to the charity * page or donation page for the selected charity. */ -public class AvailableOrganizationController extends BaseController - implements NavbarFooterController { +public class AvailableOrganizationController extends BaseController { @FXML private TextField searchField; @FXML private FlowPane cardsContainer; + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; private Charity charity; private List allCharities; + @Override + protected void authTokenisSet(){ + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } + /** * This method is used to initialize the available organization page. It retrieves all charities * from the database and sets up a listener on the search field to filter the charities based on @@ -93,8 +97,7 @@ private void displayCharities(List charities) { for (Charity charity : charities) { try { - FXMLLoader loader = - new FXMLLoader(getClass().getResource("/fxml/components/organizationCard.fxml")); + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/organizationCard.fxml")); Parent card = loader.load(); OrganizationCardController cardController = loader.getController(); @@ -121,13 +124,14 @@ public void setInitialSearch(String query) { searchField.setText(query); } + /** * This method is used to switch to the charity page for the selected charity. * * @param event action event from button click */ public void switchToCharityPage(ActionEvent event) { - LoaderScene.LoadScene("CharityPage", event, charity, null); + LoaderScene.LoadScene("CharityPage", event, charity, null, authToken); } /** @@ -137,6 +141,6 @@ public void switchToCharityPage(ActionEvent event) { */ @FXML public void switchToDonationPage(ActionEvent event) { - LoaderScene.LoadScene("DonationPage", event, charity, null); + LoaderScene.LoadScene("DonationPage", event, charity, null, authToken); } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CharityPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CharityPageController.java index d831b25..44a66b6 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CharityPageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CharityPageController.java @@ -1,10 +1,10 @@ package ntnu.systemutvikling.team6.controller; +import javafx.event.ActionEvent; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; @@ -15,14 +15,17 @@ import javafx.scene.layout.VBox; import javafx.scene.shape.Arc; import javafx.scene.shape.Rectangle; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.FooterController; import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; import ntnu.systemutvikling.team6.models.Charity; /** * This controller represents the charity page, where the user can read about the charity and choose * to donate to it. It also has a button to return to the front page. */ -public class CharityPageController { +public class CharityPageController extends BaseController { @FXML private TextField charitySearchField; @FXML private Label CharityDescription; @@ -47,9 +50,19 @@ public class CharityPageController { @FXML private VBox categoriesContainer; + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + @FXML public void initialize() {} + @Override + protected void authTokenisSet(){ + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } + + private Charity charity; /** @@ -69,6 +82,7 @@ public void setCharity(Charity charity) { CharityDescription.setText(charity.getDescription()); CharityName.setText(charity.getName()); + if (this.charity.getLogoBlob() != null) { ByteArrayInputStream logoByteStream = new ByteArrayInputStream(this.charity.getLogoBlob()); Image CharityLogoImage = new Image(logoByteStream); @@ -112,13 +126,13 @@ public void setCharity(Charity charity) { @FXML public void switchToDonationPage(ActionEvent event) { System.out.println("Click"); - LoaderScene.LoadScene("donationPage", event, charity, null); + LoaderScene.LoadScene("donationPage", event, charity, null, authToken); } @FXML public void switchToFrontPage(ActionEvent event) { System.out.println("Click"); - LoaderScene.LoadScene("FrontPage", event, charity, null); + LoaderScene.LoadScene("FrontPage", event, charity, null, authToken); } /** @@ -127,14 +141,9 @@ public void switchToFrontPage(ActionEvent event) { * @param event is the event that triggered the search. */ @FXML - public void handleSearch(ActionEvent event) { - String query = charitySearchField.getText().trim(); - - if (query.isEmpty()) { - return; - } + private void switchToFeedbackPage(ActionEvent event){ + LoaderScene.LoadScene("giveFeedback", event, charity, null, authToken); - LoaderScene.LoadScene("availableOrganization", event, null, query); } /** diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CreateUserPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CreateUserPageController.java new file mode 100644 index 0000000..75dd33c --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/CreateUserPageController.java @@ -0,0 +1,85 @@ +package ntnu.systemutvikling.team6.controller; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.FooterController; +import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; + + + +public class CreateUserPageController extends BaseController { + @FXML + private NavbarController navbarController; + @FXML + private FooterController footerController; + + @FXML private TextField firstNameField; + @FXML private TextField emailField; + @FXML private PasswordField passwordField; + @FXML private PasswordField confirmPasswordField; + + + @Override + protected void authTokenisSet() { + if (isLoggedin()){ + LoaderScene.LoadScene("frontPage", new ActionEvent(), null, null, authToken); + } + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } + + @FXML + private void handleCreateAccount(ActionEvent event){ + String nameText = firstNameField.getText(); + String emailText = emailField.getText(); + String password = passwordField.getText(); + String confirmPassword = confirmPasswordField.getText(); + + if (nameText.isBlank() || emailText.isBlank() || password.isBlank() || confirmPassword.isBlank()) { + showAlert(Alert.AlertType.ERROR, "Empty input", "Please fill out all fields"); + return; + } + + if (emailText == null || emailText.isBlank() || !emailText.contains("@") || !emailText.contains(".")) { + showAlert(Alert.AlertType.ERROR, "Invalid Email", "Please enter a valid email"); + return; + } + + if (!password.equals(confirmPassword)) { + showAlert(Alert.AlertType.ERROR, "Mismatch of password", "Password do not match"); + return; + } + + // login + boolean registerSuccess; + try { + registerSuccess = authToken.register(nameText,emailText, confirmPassword); + } catch (IllegalArgumentException e) { + showAlert(Alert.AlertType.ERROR, "Email already taken", "Email already taken by another user."); + return; + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + + } + if (registerSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Sign up sucsess", + "You have registered a new account! Please login with same credentials"); + LoaderScene.LoadScene("loginSite", event, null, null, authToken); + } + } + + @FXML + private void switchToLoginPage(ActionEvent event){ + System.out.println("Click!"); + LoaderScene.LoadScene("loginSite", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java index 0a50008..2e8b09c 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java @@ -1,32 +1,63 @@ package ntnu.systemutvikling.team6.controller; +import java.sql.Date; +import java.time.LocalDate; import java.util.Optional; + +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; +import javafx.scene.control.*; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.FooterController; import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; import ntnu.systemutvikling.team6.database.DAO.DonationDAO; +import ntnu.systemutvikling.team6.database.DAO.FavouritesDAO; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Donation; import ntnu.systemutvikling.team6.models.user.User; /** * This controller represents the donation page, where the user can enter a donation amount and * confirm their donation to the charity. It also has a button to return to the front page. */ -public class DonationPageController { +public class DonationPageController extends BaseController { @FXML private Charity charity; @FXML private TextField donatioAmount; @FXML private Label CharityName; - + @FXML private ToggleButton heartButton; @FXML private TextField donationSearchField; - private DonationDAO donationSender = new DonationDAO(new DatabaseConnection()); + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + + DatabaseConnection conn = new DatabaseConnection(); + private DonationDAO donationSender = new DonationDAO(conn); + private FavouritesDAO favouritesDAO = new FavouritesDAO(conn); + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + populateFields(); + } /** * Initialize method for the donation page. Sets the charity name label to the name of the charity @@ -42,22 +73,35 @@ public void setCharity(Charity charity) { CharityName.setText(charity.getName()); } - /** - * This method is used to switch back to the front page when the user clicks the back button. - * - * @param event - */ - public void switchToFrontPage(ActionEvent event) { - LoaderScene.LoadScene("FrontPage", event, null, null); + private void populateFields(){ + boolean isFavourite = favouritesDAO.isFavourite(authToken.getCurrentUser(), charity); + heartButton.setSelected(isFavourite); + updateHeartIcon(isFavourite); } + @FXML + private void onHeartToggle() { + boolean selected = heartButton.isSelected(); + User user = authToken.getCurrentUser(); + if (selected) { + favouritesDAO.addFavourite(user, charity); + } else { + favouritesDAO.removeFavourite(user, charity); + } + + updateHeartIcon(selected); + } + + private void updateHeartIcon(boolean selected) { + heartButton.setText(selected ? "♥" : "♡"); + } /** * This method is used to switch back to the Donation page when the user clicks the back button. * * @param event */ public void switchToCharityPage(ActionEvent event) { - LoaderScene.LoadScene("charityPage", event, charity, null); + LoaderScene.LoadScene("charityPage", event, charity, null,authToken); } /** @@ -94,6 +138,18 @@ public void Donate(ActionEvent event) { return; } + Optional resultAnonymous = Optional.empty(); + if (authToken.getCurrentUser().getSettings().isAnonymous()){ + Alert confirmAnonymous = new Alert(Alert.AlertType.CONFIRMATION); + confirmAnonymous.setTitle("You're going to donate Anonymously"); + confirmAnonymous.setHeaderText("You're about to make an anonymous donation. The charity and other donors will not be able to see your name amd email assosiated with the donation"); + confirmAnonymous.setContentText("Are you sure?"); + resultAnonymous = confirmAnonymous.showAndWait(); + if (resultAnonymous.isPresent() && resultAnonymous.get() == ButtonType.CANCEL){ + return; + } + } + Alert confirm = new Alert(Alert.AlertType.CONFIRMATION); confirm.setTitle("Confirm Donation"); confirm.setHeaderText("You're about to donate " + amount + " to " + charity.getName()); @@ -101,43 +157,17 @@ public void Donate(ActionEvent event) { Optional result = confirm.showAndWait(); if (result.isPresent() && result.get() == ButtonType.OK) { - // Process donation - // processDonation(charity, user, amount); + Donation donation = new Donation(amount, LocalDate.now(), charity, authToken.getCurrentUser()); + donationSender.addDonation(donation); showAlert( Alert.AlertType.INFORMATION, "Thank you!", "You have donated " + amount + " to " + charity.getName()); donatioAmount.clear(); - LoaderScene.LoadScene("FrontPage", event, null, null); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); } } - /** - * Invoke DAO object to add the donation to the database. This method is called from the Donate - * method after the user confirms their donation. - * - * @param charity - * @param amount - */ - public void processDonation(Charity charity, User user, double amount) { - donationSender.addDonation(charity, user, amount); - } - - /** - * Show an JavaFx alert dialog with the specified type, title, and message. - * - * @param type - * @param title - * @param message - */ - private void showAlert(Alert.AlertType type, String title, String message) { - Alert alert = new Alert(type); - alert.setTitle(title); - alert.setHeaderText(null); - alert.setContentText(message); - alert.showAndWait(); - } - /** * This method is used to handle the search action when the user clicks the search button. * @@ -151,6 +181,6 @@ public void handleSearch(ActionEvent event) { return; } - LoaderScene.LoadScene("availableOrganization", event, null, query); + LoaderScene.LoadScene("availableOrganization", event, null, query, authToken); } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java index 1fd15cd..a4bd599 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java @@ -5,18 +5,18 @@ import java.util.List; import java.util.Objects; import java.util.Random; + +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; +import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.FlowPane; -import ntnu.systemutvikling.team6.controller.components.BaseController; -import ntnu.systemutvikling.team6.controller.components.LoaderScene; -import ntnu.systemutvikling.team6.controller.components.NavbarFooterController; -import ntnu.systemutvikling.team6.controller.components.OrganizationCardController; +import ntnu.systemutvikling.team6.controller.components.*; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.database.Readers.CategorySelect; import ntnu.systemutvikling.team6.database.Readers.CharitySelect; @@ -33,7 +33,7 @@ * it, or click on the featured charity to see more details about it. It also has buttons to switch * to the charity page and the donation page for the featured charity */ -public class FrontpageController extends BaseController implements NavbarFooterController { +public class FrontpageController extends BaseController{ @FXML private Charity featuredCharity; @FXML private FlowPane cardsContainer; @FXML private Label Carosel_Organisasjon; @@ -41,15 +41,24 @@ public class FrontpageController extends BaseController implements NavbarFooterC @FXML private Label Total_Orgnisasjon; @FXML private Label Total_Donations; @FXML private Label PreApproved_Percentage; - @FXML private TextField frontSearchField; + @FXML private CheckBox verifiedFilter; @FXML private javafx.scene.layout.VBox categoryList; private final List selectedCategories = new ArrayList<>(); + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + private List allCharities = new ArrayList<>(); + + @Override - protected void authTokenisSet() {} + protected void authTokenisSet(){ + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + loadPage(); + } /** * Initialize method for the front page. This method is called when the front page is loaded. It @@ -61,6 +70,10 @@ protected void authTokenisSet() {} */ @FXML public void initialize() { + + } + + private void loadPage(){ try { DatabaseConnection conn = new DatabaseConnection(); CharitySelect cdb = new CharitySelect(conn); @@ -101,15 +114,15 @@ public void initialize() { Total_Orgnisasjon.setText(Integer.toString(charitiesSize)); Total_Donations.setText( - Double.toString( - donations.getAllDonations().stream().mapToDouble(Donation::getAmount).sum())); + Double.toString( + donations.getAllDonations().stream().mapToDouble(Donation::getAmount).sum())); PreApproved_Percentage.setText( - String.format( - "%.2f", - charities.getAllCharities().stream().filter(Charity::getPreApproved).count() - * 100.0 - / charitiesSize) - + "%"); + String.format( + "%.2f", + charities.getAllCharities().stream().filter(Charity::getPreApproved).count() + * 100.0 + / charitiesSize) + + "%"); } catch (Exception e) { e.printStackTrace(); } @@ -121,7 +134,7 @@ public void initialize() { * @param event */ public void switchToCharityPage(ActionEvent event) { - LoaderScene.LoadScene("CharityPage", event, featuredCharity, null); + LoaderScene.LoadScene("CharityPage", event, featuredCharity, null, authToken); } /** @@ -130,7 +143,7 @@ public void switchToCharityPage(ActionEvent event) { * @param event */ public void switchToDonationPage(ActionEvent event) { - LoaderScene.LoadScene("DonationPage", event, featuredCharity, null); + LoaderScene.LoadScene("DonationPage", event, featuredCharity, null, authToken); } /** @@ -143,22 +156,6 @@ public void handleCategoryFilterChange(ActionEvent event) { displayCharities(getFilteredCharities()); } - /** - * This method is used to search for charities based on the input in the search field. - * - * @param event is the event that triggered the search. - */ - @FXML - public void handleFrontSearch(ActionEvent event) { - String query = frontSearchField.getText().trim(); - - if (query.isEmpty()) { - return; - } - - LoaderScene.LoadScene("availableOrganization", event, null, query); - } - /** * This method is used to filter the charities based on the selected filters. * @@ -215,6 +212,7 @@ private void displayCharities(List charities) { Parent card = loader.load(); OrganizationCardController cardController = loader.getController(); cardController.setOrganization(charity); + cardController.setAuthToken(authToken); cardsContainer.getChildren().add(card); } catch (IOException e) { throw new RuntimeException("Could not load organization card.", e); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/GiveFeedbackController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/GiveFeedbackController.java new file mode 100644 index 0000000..1870da0 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/GiveFeedbackController.java @@ -0,0 +1,110 @@ +package ntnu.systemutvikling.team6.controller; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.layout.FlowPane; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DAO.FeedbackDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.CharitySelect; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Feedback; + +import java.io.IOException; +import java.util.ArrayList; + +public class GiveFeedbackController extends BaseController { + private Charity charity; + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + + @FXML private FlowPane feedbackContainer; + @FXML private Label charityNameLabel; + @FXML private TextArea feedbackCommentArea; + + + + @FXML + public void setCharity(Charity charity) { + this.charity = charity; + + charityNameLabel.setText(charity.getName()); + } + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + populateFields(); + } + private void populateFields(){ + DatabaseConnection conn = new DatabaseConnection(); + CharitySelect charitySelect = new CharitySelect(conn); + ArrayList feedbacks = charitySelect.getFeedbackforCharityUUID(charity.getUUID().toString()); + displayFeedbacks(feedbacks); + } + private void displayFeedbacks(ArrayList feedbacks){ + feedbackContainer.getChildren().clear(); + if (feedbacks.isEmpty()) { + javafx.scene.control.Label empty = new javafx.scene.control.Label("You have no Feedbacks"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + feedbackContainer.getChildren().add(empty); + } + + for (Feedback feedback : feedbacks) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/feedbackCard.fxml")); + Parent card = loader.load(); + FeedbackCardController cardController = loader.getController(); + cardController.setMessage(feedback); + cardController.setAuthToken(authToken); + feedbackContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + @FXML + private void handleSubmitFeedback(ActionEvent event){ + String feedbackCommentAreaText = feedbackCommentArea.getText(); + Feedback newFeedback = new Feedback(authToken.getCurrentUser(), feedbackCommentAreaText); + + DatabaseConnection conn = new DatabaseConnection(); + FeedbackDAO feedbackDAO = new FeedbackDAO(conn); + boolean submitSuccess; + try { + submitSuccess = feedbackDAO.addFeedbackToCharity(newFeedback, charity); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (submitSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Feedback received", + charity.getName() + " has gotten your feedback"); + LoaderScene.LoadScene("charityPage", event, charity, null, authToken); + } + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/LoginPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/LoginPageController.java new file mode 100644 index 0000000..3e13f25 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/LoginPageController.java @@ -0,0 +1,76 @@ +package ntnu.systemutvikling.team6.controller; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.FooterController; +import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; + +import java.awt.*; + + +public class LoginPageController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private FooterController footerController; + + @FXML private TextField emailField; + @FXML private PasswordField passwordField; + + @Override + protected void authTokenisSet() { + if (isLoggedin()){ + LoaderScene.LoadScene("frontPage", new ActionEvent(), null, null, authToken); + } + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } + + @FXML + private void handleLogin(ActionEvent event){ + String emailText = emailField.getText(); + String password = passwordField.getText(); + + if (emailText.isBlank() || password.isBlank()){ + showAlert(Alert.AlertType.ERROR, "Empty input", "Please fill out all fields"); + return; + } + + if (!emailText.contains("@") || !emailText.contains(".")) { + showAlert(Alert.AlertType.ERROR, "Invalid Email", "Please enter a valid email"); + return; + } + + boolean loginSuccess; + try { + loginSuccess = authToken.login(emailText, password); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (loginSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Login Success", + "Login Successful!"); + LoaderScene.LoadScene("profile_user_Settings", event, null, null, authToken); + } else { + showAlert( + Alert.AlertType.ERROR, + "Account not found", + "User logg inn failed. Either email is wrong or password"); + emailField.setText(""); + passwordField.setText(""); + } + } + + @FXML + private void switchToSignupPage(ActionEvent event){ + System.out.println("Click!"); + LoaderScene.LoadScene("creater_user_site", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/BaseController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/BaseController.java index a42a466..48ceb2e 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/BaseController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/BaseController.java @@ -1,19 +1,55 @@ package ntnu.systemutvikling.team6.controller.components; + +import javafx.scene.control.Alert; import ntnu.systemutvikling.team6.service.AuthenticationService; + public abstract class BaseController { - protected AuthenticationService authToken; + protected AuthenticationService authToken; + + public void setAuthToken(AuthenticationService authToken){ + this.authToken = authToken; + authTokenisSet(); + }; + protected abstract void authTokenisSet(); + // Update ui (login button or profile circle) after authtoken is set: + // Make sure to invoke navbarController.setAuthtoken AND FooterController on controller that have @FXML private navbarController as an attribute. + // If footerController and NavbarController on the same file overwrite one of the controllers switchtofrontpage. + + + + protected boolean isLoggedin(){ + return authToken != null && authToken.isLoggedin(); + } + + + /** + * Show an JavaFx alert dialog with the specified type, title, and message. + * + * @param type + * @param title + * @param message + */ + protected void showAlert(Alert.AlertType type, String title, String message) { + Alert alert = new Alert(type); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } - public void setAuthToken(AuthenticationService authToken) { - this.authToken = authToken; - authTokenisSet(); - } - ; + // Example on the minimum inside of a controller that extends the baseControlle and inserts footer and navbar fxml: + /* + @FXML + private NavbarController navbarController; + @FXML private FooterController footerController; - protected void authTokenisSet() {} // Do stuff after authtoken is set, on each controller + @Override + protected void authTokenisSet() { + navbarController.setAuthToken(authToken); + footerController.setAuthToken(authToken); + } + */ - protected boolean isLoggedin() { - return authToken.isLoggedin() && authToken != null; - } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/CategoryTagController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/CategoryTagController.java new file mode 100644 index 0000000..5fecbbc --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/CategoryTagController.java @@ -0,0 +1,42 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.fxml.FXML; +import javafx.scene.control.Button; + +public class CategoryTagController extends BaseController{ + @FXML private Button button; + private static final String[][] TAG_COLORS = { + {"#E5F0D7", "#6E8A5C"}, // green + {"#D7E8F0", "#5C7A8A"}, // blue + {"#F0E5D7", "#8A6E5C"}, // orange + {"#EFD7F0", "#8A5C8A"}, // purple + {"#F0D7D7", "#8A5C5C"}, // red + {"#D7F0EE", "#5C8A87"}, // teal + {"#F0EDD7", "#8A845C"}, // yellow + }; + + private String[] getRandomTagColor() { + return TAG_COLORS[(int) (Math.random() * TAG_COLORS.length)]; + } + + private String category; + + @Override + protected void authTokenisSet() { + + } + + public void setCategory(String category) { + this.category = category; + + button.setText(category); + String[] colors = getRandomTagColor(); + button.setStyle( + "-fx-background-color: " + colors[0] + ";" + + "-fx-text-fill: " + colors[1] + ";" + + "-fx-background-radius: 20;" + + "-fx-font-size: 11px;" + + "-fx-padding: 4 10 4 10;" + ); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/DonationCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/DonationCardController.java new file mode 100644 index 0000000..596f18d --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/DonationCardController.java @@ -0,0 +1,31 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.user.Message; + +public class DonationCardController extends BaseController{ + @FXML private Label charityNameLabel; + @FXML private Label purchaseIDLabel; + @FXML private Label dateLabel; + @FXML private Label AnonymousLabel; + @FXML private Label totalLabel; + + private Donation donation; + + @Override + protected void authTokenisSet() { + + } + + public void setDonation(Donation donation) { + this.donation = donation; + + charityNameLabel.setText(donation.getCharity().getName()); + purchaseIDLabel.setText(donation.getDonationID().toString()); + dateLabel.setText(donation.getDate().toString()); + AnonymousLabel.setText(donation.isAnonymous() ? "Yes" : "No"); + totalLabel.setText(String.valueOf(donation.getAmount())); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FeedbackCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FeedbackCardController.java new file mode 100644 index 0000000..987c731 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FeedbackCardController.java @@ -0,0 +1,28 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.user.Message; + +public class FeedbackCardController extends BaseController { + @FXML private Label usernameLabel; + @FXML private Label dateLabel; + @FXML private Label commentLabel; + + private Feedback feedback; + + @Override + protected void authTokenisSet() { + + } + + public void setMessage(Feedback feedback) { + this.feedback = feedback; + + System.out.println(feedback.isAnonymous()); + usernameLabel.setText(feedback.isAnonymous() ? "Anonymous Doner" : feedback.getUser().getUsername()); + dateLabel.setText(feedback.getDate().toString()); + commentLabel.setText(feedback.getComment()); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FooterController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FooterController.java new file mode 100644 index 0000000..05e25d1 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/FooterController.java @@ -0,0 +1,26 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.service.AuthenticationService; + +public class FooterController extends BaseController { + @FXML + private void switchToAboutPage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("aboutPage", event, null, null, authToken); + } + @FXML + private void switchToFrontPage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("frontPage", event, null, null, authToken); + } + + @Override + protected void authTokenisSet() { + + + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InboxCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InboxCardController.java new file mode 100644 index 0000000..be0b2b0 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InboxCardController.java @@ -0,0 +1,31 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.Message; + +public class InboxCardController extends BaseController{ + @FXML private Label messageFrom; + @FXML private Label messageTitle; + @FXML private Label messageContent; + @FXML private Label messageDate; + + private Message message; + + @Override + protected void authTokenisSet() { + + } + + public void setMessage(Message message) { + this.message = message; + + messageFrom.setText(message.getFrom().getName()); + messageTitle.setText(message.getTitle()); + messageContent.setText(message.getContent()); + messageDate.setText(message.getTimeAndDate().toString()); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InterestCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InterestCardController.java new file mode 100644 index 0000000..e7aec6f --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/InterestCardController.java @@ -0,0 +1,48 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.models.Charity; + +public class InterestCardController extends BaseController{ + @FXML private Label charityDescription; + @FXML private Label verifyLabel; + @FXML private Label charityNameLabel; + + @FXML private Button detailsButton; + @FXML private Button donateButton; + + private Charity charity; + + @Override + protected void authTokenisSet() { + + } + + public void setOrganization(Charity charity) { + this.charity = charity; + + charityNameLabel.setText(charity.getName()); + verifyLabel.setText(charity.getPreApproved() ? "Verify" : "Unverified"); + verifyLabel.setStyle(charity.getPreApproved() ? "-fx-background-color: #2f8f3a; -fx-alignment: CENTER_LEFT; -fx-text-fill: white;" : "-fx-alignment: CENTER_LEFT; -fx-background-color: #D11D27; -fx-text-fill: white;"); + charityDescription.setText(charity.getDescription()); + + if(charity.getName().equals("You have no Favourites")){ + detailsButton.setVisible(false); + donateButton.setVisible(false); + } + } + + /* EVENTS */ + @FXML + private void switchToCharity(ActionEvent event){ + LoaderScene.LoadScene("CharityPage", event, charity, null, authToken); + } + + @FXML + private void switchToDonate(ActionEvent event){ + LoaderScene.LoadScene("DonationPage", event, charity, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/LoaderScene.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/LoaderScene.java index 30236e9..d9ec09a 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/LoaderScene.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/LoaderScene.java @@ -10,10 +10,9 @@ import javafx.scene.image.Image; import javafx.stage.Stage; import ntnu.systemutvikling.team6.HmHApplication; -import ntnu.systemutvikling.team6.controller.AvailableOrganizationController; -import ntnu.systemutvikling.team6.controller.CharityPageController; -import ntnu.systemutvikling.team6.controller.DonationPageController; +import ntnu.systemutvikling.team6.controller.*; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.service.AuthenticationService; /** * This class is a utility class that is used to load different scenes in the application. For now, @@ -22,16 +21,14 @@ */ public class LoaderScene { /** - * When going to a new scene, this method is called to load the new scene. It takes the name of - * the scene to load, the event that triggered the scene change, and the charity that is being - * passed to the new scene (if applicable). It loads the FXML file for the new scene, sets the - * controller, and switches the scene. + * When going to a new scene, this method and another called to load the new scene. + * It loads the FXML file for the new scene, sets the controller, and switches the scene. * * @param sceneName * @param event * @param charity */ - public static void LoadScene(String sceneName, ActionEvent event, Charity charity, String query) { + public static void LoadScene(String sceneName, Stage stage, Charity charity, String query, AuthenticationService authtoken) { try { System.out.println(HmHApplication.class.getResource("/fxml/" + sceneName + ".fxml")); FXMLLoader fxmlLoader = @@ -42,17 +39,31 @@ public static void LoadScene(String sceneName, ActionEvent event, Charity charit Object controller = fxmlLoader.getController(); // Needs to be expanded when more pages get implemented. - if (controller instanceof CharityPageController charityController) { - charityController.setCharity(charity); + // Controllers that need charities: + if (charity != null){ + if (controller instanceof CharityPageController charityController) { + charityController.setCharity(charity); + } + if (controller instanceof DonationPageController donationController) { + donationController.setCharity(charity); + } + if (controller instanceof GiveFeedbackController giveFeedbackController) { + giveFeedbackController.setCharity(charity); + } } - if (controller instanceof DonationPageController donationController) { - donationController.setCharity(charity); + + // Controllers that need query + if (query != null){ + if (controller instanceof AvailableOrganizationController availableOrganizationController) { + availableOrganizationController.setInitialSearch(query); + } } - if (controller instanceof AvailableOrganizationController availableOrganizationController) { - availableOrganizationController.setInitialSearch(query); + + // All controllers need to set authtoken + if (controller instanceof BaseController baseController){ + baseController.setAuthToken(authtoken); } - Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); Image icon = new Image( Objects.requireNonNull(HmHApplication.class.getResource("/images/Logo.png")) @@ -66,4 +77,15 @@ public static void LoadScene(String sceneName, ActionEvent event, Charity charit throw new RuntimeException(e); } } + /** + * This method is the same as above, but tailored for Action Events, say through clicking a button. + * It takes the name of + * * the scene to load, the event that triggered the scene change, and the charity that is being + * * passed to the new scene (if applicable). + */ + + public static void LoadScene(String sceneName, ActionEvent event, Charity charity, String query, AuthenticationService authtoken) { + Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); + LoadScene(sceneName, stage, charity, query, authtoken); + } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarController.java new file mode 100644 index 0000000..8052ef1 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarController.java @@ -0,0 +1,75 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.event.ActionEvent; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; + +import java.awt.*; +import java.awt.event.MouseEvent; + +public class NavbarController extends BaseController { + @FXML protected TextField frontSearchField; + @FXML private Button loginButton; + @FXML private Button profileButton; + @FXML private Button toCharityUserButton; + + @Override + protected void authTokenisSet() { + boolean loggedIn = super.isLoggedin(); + if (loggedIn){ + if (authToken.isCharityUser() != null){ + toCharityUserButton.setVisible(true); + toCharityUserButton.setManaged(true); + } + loginButton.setVisible(false); + loginButton.setManaged(false); + profileButton.setVisible(true); + profileButton.setManaged(true); + profileButton.setText(authToken.getCurrentUser().getUsername().substring(0,2).toUpperCase().trim()); + } else { + loginButton.setVisible(true); + loginButton.setManaged(true); + profileButton.setVisible(false); + profileButton.setManaged(false); + toCharityUserButton.setVisible(false); + toCharityUserButton.setManaged(false); + } + + } + @FXML + private void handleFrontSearch(ActionEvent event){ + String query = frontSearchField.getText().trim(); + + if (query.isEmpty()) { + return; + } + + LoaderScene.LoadScene("available_organizations", event, null, query, authToken); + } + + @FXML + private void switchToFrontPage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("frontPage", event, null, null, authToken); + } + + @FXML + private void switchToProfilePage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } + + @FXML + private void switchToLoginPage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("loginSite", event, null, null, authToken); + } + + @FXML + private void switchToCharityUserPage(ActionEvent event) { + System.out.println("Click!"); + LoaderScene.LoadScene("profile_org_settings", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarFooterController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarFooterController.java deleted file mode 100644 index 3f12e26..0000000 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/NavbarFooterController.java +++ /dev/null @@ -1,31 +0,0 @@ -package ntnu.systemutvikling.team6.controller.components; - -import javafx.event.ActionEvent; - -public interface NavbarFooterController { - - default void switchToFrontPage(ActionEvent event) { - System.out.println("Click!"); - LoaderScene.LoadScene("FrontPage", event, null, null); - } - - default void switchToAboutPage(ActionEvent event) { - System.out.println("Click!"); - LoaderScene.LoadScene("aboutPage", event, null, null); - } - - default void switchToProfilePage(ActionEvent event) { - System.out.println("Click!"); - LoaderScene.LoadScene("aboutPage", event, null, null); - } - - default void handleSearch(ActionEvent event) { - System.out.println("Click!"); - LoaderScene.LoadScene("aboutPage", event, null, null); - } - - default void switchToLoginPage(ActionEvent event) { - System.out.println("Click!"); - LoaderScene.LoadScene("aboutPage", event, null, null); - } -} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrgDonationCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrgDonationCardController.java new file mode 100644 index 0000000..5fcbe69 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrgDonationCardController.java @@ -0,0 +1,28 @@ +package ntnu.systemutvikling.team6.controller.components; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import ntnu.systemutvikling.team6.models.Donation; + +public class OrgDonationCardController extends BaseController{ + @FXML private Label donerNameLabel; + @FXML private Label purchaseIDLabel; + @FXML private Label dateLabel; + @FXML private Label totalLabel; + + private Donation donation; + + @Override + protected void authTokenisSet() { + + } + + public void setDonation(Donation donation) { + this.donation = donation; + + donerNameLabel.setText(donation.isAnonymous() ? "Anonymous Doner" : donation.getCharity().getName()); + purchaseIDLabel.setText(donation.getDonationID().toString()); + dateLabel.setText(donation.getDate().toString()); + totalLabel.setText(String.valueOf(donation.getAmount())); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrganizationCardController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrganizationCardController.java index 7644bbf..3d7c53e 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrganizationCardController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/components/OrganizationCardController.java @@ -10,7 +10,7 @@ * looped upon in FronpageController. It is used to display the name and description of a charity, * and to switch to the charity page or donation page when the user clicks on the card. */ -public class OrganizationCardController { +public class OrganizationCardController extends BaseController { @FXML private Label organizationName; @@ -18,6 +18,11 @@ public class OrganizationCardController { private Charity charity; + @Override + protected void authTokenisSet() { + + } + public void setOrganization(Charity charity) { this.charity = charity; @@ -27,10 +32,13 @@ public void setOrganization(Charity charity) { /* EVENTS */ public void switchToCharityPage(ActionEvent event) { - LoaderScene.LoadScene("CharityPage", event, charity, null); + LoaderScene.LoadScene("CharityPage", event, charity, null, authToken); } public void switchToDonationPage(ActionEvent event) { - LoaderScene.LoadScene("DonationPage", event, charity, null); + System.out.println(authToken.getCurrentUser().getId().toString()); + LoaderScene.LoadScene("DonationPage", event, charity, null, authToken); } + + } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgEditController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgEditController.java new file mode 100644 index 0000000..5ad1d17 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgEditController.java @@ -0,0 +1,112 @@ +package ntnu.systemutvikling.team6.controller.profileCharity; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.CategoryTagController; +import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; +import ntnu.systemutvikling.team6.database.DAO.CharityUserDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; + +import java.io.IOException; +import java.util.List; + +public class profileOrgEditController extends BaseController { + @FXML + private NavbarController navbarController; + @FXML private Label charityNameLabel; + @FXML private TextArea descriptionField; + + @Override + protected void authTokenisSet() { + if (!isLoggedin() || authToken.isCharityUser() == null){ + showAlert(Alert.AlertType.ERROR, "Not logged inn or dont have privileges", "You need to be logged inn an account with Charity User priviliges."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + return; + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + private void populateFields(){ + Charity usersCharity = authToken.isCharityUser(); + charityNameLabel.setText(usersCharity.getName()); + descriptionField.setText(usersCharity.getDescription()); + } + + @FXML + private void handleSaveDescription(ActionEvent event){ + String descriptionFieldText = descriptionField.getText(); + + + if (descriptionFieldText.isBlank()) { + showAlert(Alert.AlertType.ERROR, "Empty input", "Yeah, maybe it was empty before but now it need one"); + return; + } + + boolean updateSuccess; + DatabaseConnection conn = new DatabaseConnection(); + CharityUserDAO userDataObject = new CharityUserDAO(conn); + Charity savedCharity = authToken.isCharityUser(); + Charity minimalCharityWithJustNewDescription = new Charity(savedCharity.getUUID().toString(), savedCharity.getOrg_number(), savedCharity.getName(), null, savedCharity.getStatus(), savedCharity.getPreApproved(),descriptionFieldText, null, null, null); + try { + updateSuccess = userDataObject.updateCharityVanityDescription(minimalCharityWithJustNewDescription); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (updateSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Settings updated", + "You have successfully changed your settings"); + authToken.isCharityUser().setDescription(descriptionFieldText); + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } else { + System.out.println("Something went wrong when updating Settings"); + } + } + + @FXML + private void switchToPaymentsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_Payments", event, null, null, authToken); + } + + @FXML + private void switchToFeedbackPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_Inbox", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_Settings", event, null, null, authToken); + } + + + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgInboxController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgInboxController.java new file mode 100644 index 0000000..6b89eee --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgInboxController.java @@ -0,0 +1,138 @@ +package ntnu.systemutvikling.team6.controller.profileCharity; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.layout.FlowPane; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DAO.MessageDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.CharitySelect; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.user.Inbox; +import ntnu.systemutvikling.team6.models.user.Message; +import ntnu.systemutvikling.team6.models.user.User; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class profileOrgInboxController extends BaseController { + @FXML + private NavbarController navbarController; + @FXML + private FlowPane cardsContainer; + @FXML private Label charityNameLabel; + @FXML private TextField messageTitleField; + @FXML private TextArea messageContentField; + + + @Override + protected void authTokenisSet() { + if (!isLoggedin() || authToken.isCharityUser() == null) { + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + public void populateFields() { + Charity usersCharity = authToken.isCharityUser(); + charityNameLabel.setText(usersCharity.getName()); + + // Messages + DatabaseConnection conn = new DatabaseConnection(); + CharitySelect charitySelect = new CharitySelect(conn); + ArrayList feedbacks = charitySelect.getFeedbackforCharityUUID(authToken.isCharityUser().getUUID().toString()); + displayFeedbacks(feedbacks); + } + + private void displayFeedbacks(ArrayList feedbacks){ + cardsContainer.getChildren().clear(); + if (feedbacks.isEmpty()) { + Label empty = new Label("You have no Feedbacks"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + cardsContainer.getChildren().add(empty); + } + + for (Feedback feedback : feedbacks) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/feedbackCard.fxml")); + Parent card = loader.load(); + FeedbackCardController cardController = loader.getController(); + cardController.setMessage(feedback); + cardController.setAuthToken(authToken); + cardsContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + @FXML + private void handleSendMessage(ActionEvent event) { + String title = messageTitleField.getText().trim(); + String content = messageContentField.getText().trim(); + + if (title.isBlank() || content.isBlank()) { + showAlert(Alert.AlertType.ERROR, "Empty fields", "Please fill in both title and message."); + return; + } + + try { + DatabaseConnection conn = new DatabaseConnection(); + MessageDAO messageDAO = new MessageDAO(conn); + Charity charity = authToken.isCharityUser(); + Message messageStaticId = new Message(title, authToken.isCharityUser(), content); + messageDAO.addMessage(messageStaticId); + showAlert(Alert.AlertType.INFORMATION, "Sent!", "Your message has been sent to all donors."); + messageTitleField.clear(); + messageContentField.clear(); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Error", "Something went wrong sending the message."); + } + } + + // Sidebar Methods + @FXML + private void switchToPaymentsPage(ActionEvent event) { + LoaderScene.LoadScene("profile_org_Payments", event, null, null, authToken); + } + + @FXML + private void switchToEditPage(ActionEvent event) { + LoaderScene.LoadScene("profile_org_edit", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event) { + LoaderScene.LoadScene("profile_user_Settings", event, null, null, authToken); + } + + + @FXML + private void handleLogout(ActionEvent event) { + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgPaymentsController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgPaymentsController.java new file mode 100644 index 0000000..de65107 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgPaymentsController.java @@ -0,0 +1,105 @@ +package ntnu.systemutvikling.team6.controller.profileCharity; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.DonationSelect; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.registry.DonationRegistry; +import ntnu.systemutvikling.team6.models.user.User; + +import java.io.IOException; +import java.util.List; + +public class profileOrgPaymentsController extends BaseController { + @FXML + private NavbarController navbarController; + @FXML private VBox cardsContainer; + @FXML private Label charityNameLabel; + + + @Override + protected void authTokenisSet() { + if (!isLoggedin() || authToken.isCharityUser() == null){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + public void populateFields() { + Charity usersCharity = authToken.isCharityUser(); + charityNameLabel.setText(usersCharity.getName()); + + // DonationHistory + DatabaseConnection conn = new DatabaseConnection(); + DonationSelect donationSelect = new DonationSelect(conn); + DonationRegistry donationRegistry = donationSelect.getDonationForCharity(authToken.isCharityUser().getUUID().toString()); + displayDonations(donationRegistry); + } + + private void displayDonations(DonationRegistry donationRegistry) { + cardsContainer.getChildren().clear(); + List donations = donationRegistry.getAllDonations(); + if(donations.isEmpty()){ + Label empty = new Label("You have no Donations"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + cardsContainer.getChildren().add(empty); + } + + for (Donation donation : donations) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/profileOrgDonationCard.fxml")); + Parent card = loader.load(); + OrgDonationCardController cardController = loader.getController(); + cardController.setDonation(donation); + cardController.setAuthToken(authToken); + cardsContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + // Sidebar Methods + @FXML + private void switchToEditPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_edit", event, null, null, authToken); + } + + @FXML + private void switchToFeedbackPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_Inbox", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_Settings", event, null, null, authToken); + } + + + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgSettingsController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgSettingsController.java new file mode 100644 index 0000000..c8b93db --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileCharity/profileOrgSettingsController.java @@ -0,0 +1,144 @@ +package ntnu.systemutvikling.team6.controller.profileCharity; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DAO.CharityUserDAO; +import ntnu.systemutvikling.team6.database.DAO.UserDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.UserSelect; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.registry.DonationRegistry; +import ntnu.systemutvikling.team6.models.user.User; +import ntnu.systemutvikling.team6.security.PasswordHasher; + +import java.io.IOException; +import java.util.Base64; +import java.util.List; + +public class profileOrgSettingsController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private Label charityNameLabel; + @FXML private TextField organizationNameField; + @FXML private HBox tagContainer; + + @Override + protected void authTokenisSet() { + if (!isLoggedin() || authToken.isCharityUser() == null){ + showAlert(Alert.AlertType.ERROR, "Not logged inn or dont have privileges", "You need to be logged inn an account with Charity User priviliges."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + return; + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + private void populateFields(){ + Charity usersCharity = authToken.isCharityUser(); + charityNameLabel.setText(usersCharity.getName()); + organizationNameField.setText(usersCharity.getName()); + + // Tags + List categories = usersCharity.getCategory(); + displayCategories(categories); + + } + + private void displayCategories(List categories) { + tagContainer.getChildren().clear(); + if(categories.isEmpty()){ + Label empty = new Label("No categories"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + tagContainer.getChildren().add(empty); + return; + } + + for (String category : categories) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/categoryTag.fxml")); + Parent card = loader.load(); + CategoryTagController cardController = loader.getController(); + cardController.setCategory(category); + cardController.setAuthToken(authToken); + tagContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + @FXML + private void handleNewName(ActionEvent event){ + String organizationNameFieldText = organizationNameField.getText(); + + + if (organizationNameFieldText.isBlank()) { + showAlert(Alert.AlertType.ERROR, "Empty input", "Please fill out all fields"); + return; + } + + boolean updateSuccess; + DatabaseConnection conn = new DatabaseConnection(); + CharityUserDAO userDataObject = new CharityUserDAO(conn); + Charity savedCharity = authToken.isCharityUser(); + Charity minimalCharityWithJustNewName = new Charity(savedCharity.getUUID().toString(), savedCharity.getOrg_number(), organizationNameFieldText, null, savedCharity.getStatus(), savedCharity.getPreApproved(),null, null, null, null); + try { + updateSuccess = userDataObject.updateCharityVanityName(minimalCharityWithJustNewName); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (updateSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Settings updated", + "You have successfully changed your settings"); + authToken.isCharityUser().setName(organizationNameFieldText); + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } else { + System.out.println("Something went wrong when updating Settings"); + } + + } + + @FXML + private void switchToPaymentsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_Payments", event, null, null, authToken); + } + + @FXML + private void switchToFeedbackPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_Inbox", event, null, null, authToken); + } + + @FXML + private void switchToEditPage(ActionEvent event){ + LoaderScene.LoadScene("profile_org_edit", event, null, null, authToken); + } + + + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserHistoryController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserHistoryController.java new file mode 100644 index 0000000..32b11a9 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserHistoryController.java @@ -0,0 +1,117 @@ +package ntnu.systemutvikling.team6.controller.profileUser; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.DonationSelect; +import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.registry.DonationRegistry; +import ntnu.systemutvikling.team6.models.user.Inbox; +import ntnu.systemutvikling.team6.models.user.Message; +import ntnu.systemutvikling.team6.models.user.User; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +public class profileUserHistoryController extends BaseController { + @FXML + private NavbarController navbarController; + @FXML private VBox cardsContainer; + @FXML private Label nameLabel; + @FXML private Label shortNameLabel; + @FXML private Label totalAmmount; + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + public void populateFields() { + User user = authToken.getCurrentUser(); + // Names + nameLabel.setText(user.getUsername()); + shortNameLabel.setText(user.getUsername().substring(0, 2).toUpperCase().trim()); + + // DonationHistory + DatabaseConnection conn = new DatabaseConnection(); + DonationSelect donationSelect = new DonationSelect(conn); + DonationRegistry donationRegistry = donationSelect.getDonationForUser(authToken.getCurrentUser().getId().toString()); + double ammount = donationRegistry.getAllDonations().stream().mapToDouble(d->d.getAmount()).sum(); + totalAmmount.setText(String.valueOf(ammount)); + displayDonations(donationRegistry); + } + + private void displayDonations(DonationRegistry donationRegistry) { + cardsContainer.getChildren().clear(); + List donations = donationRegistry.getAllDonations(); + if(donations.isEmpty()){ + Label empty = new Label("You have no Donations"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + cardsContainer.getChildren().add(empty); + } + + for (Donation donation : donations) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/profileDonationCard.fxml")); + Parent card = loader.load(); + DonationCardController cardController = loader.getController(); + cardController.setDonation(donation); + cardController.setAuthToken(authToken); + cardsContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + // Sidebar Methods + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToFrontPage(ActionEvent event){ + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToInterestPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_interests", event, null, null, authToken); + } + + @FXML + private void switchToInboxPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_inbox", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInboxController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInboxController.java new file mode 100644 index 0000000..3935270 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInboxController.java @@ -0,0 +1,111 @@ +package ntnu.systemutvikling.team6.controller.profileUser; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DAO.FavouritesDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.Inbox; +import ntnu.systemutvikling.team6.models.user.Message; +import ntnu.systemutvikling.team6.models.user.Settings; +import ntnu.systemutvikling.team6.models.user.User; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class profileUserInboxController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private FlowPane cardsContainer; + @FXML private Label nameLabel; + @FXML private Label shortNameLabel; + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + public void populateFields() { + User user = authToken.getCurrentUser(); + // Names + nameLabel.setText(user.getUsername()); + shortNameLabel.setText(user.getUsername().substring(0, 2).toUpperCase().trim()); + + // Messages + Inbox inbox = authToken.getCurrentUser().getInbox(); + displayInbox(inbox); + } + + private void displayInbox(Inbox inbox) { + cardsContainer.getChildren().clear(); + List messages = inbox.getMessages(); + if(messages.isEmpty()){ + Label empty = new Label("You have no messages"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + cardsContainer.getChildren().add(empty); + } + + for (Message message : messages) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/inboxCard.fxml")); + Parent card = loader.load(); + InboxCardController cardController = loader.getController(); + cardController.setMessage(message); + cardController.setAuthToken(authToken); + cardsContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + // Sidebar Methods + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToFrontPage(ActionEvent event){ + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToInterestPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_interests", event, null, null, authToken); + } + + @FXML + private void switchToHistoryPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_history", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInterestController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInterestController.java new file mode 100644 index 0000000..7ebffcf --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserInterestController.java @@ -0,0 +1,115 @@ +package ntnu.systemutvikling.team6.controller.profileUser; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.*; +import ntnu.systemutvikling.team6.database.DAO.FavouritesDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; +import ntnu.systemutvikling.team6.models.user.Language; +import ntnu.systemutvikling.team6.models.user.Settings; +import ntnu.systemutvikling.team6.models.user.User; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class profileUserInterestController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private FlowPane cardsContainer; + @FXML private Label nameLabel; + @FXML private Label shortNameLabel; + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + + public void populateFields() { + User user = authToken.getCurrentUser(); + Settings settings = user.getSettings(); + // Names + nameLabel.setText(user.getUsername()); + shortNameLabel.setText(user.getUsername().substring(0, 2).toUpperCase().trim()); + + // Favourites + DatabaseConnection conn = new DatabaseConnection(); + FavouritesDAO favouritesDAO = new FavouritesDAO(conn); + ArrayList favourites = new ArrayList<>(favouritesDAO.getFavouritesForUser(authToken.getCurrentUser().getId().toString())); + displayFavourites(favourites); + } + + private void displayFavourites(ArrayList favourites) { + cardsContainer.getChildren().clear(); + if(favourites.isEmpty()){ + Label empty = new Label("You have no favourited Charities"); + empty.setStyle("-fx-text-fill: #777777; -fx-font-size: 14;"); + cardsContainer.getChildren().add(empty); + } + + for (Charity charity : favourites) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/components/interestCard.fxml")); + Parent card = loader.load(); + InterestCardController cardController = loader.getController(); + cardController.setOrganization(charity); + cardController.setAuthToken(authToken); + cardsContainer.getChildren().add(card); + } catch (IOException e) { + throw new RuntimeException("Could not load organization card.", e); + } + } + } + + // Sidebar Methods + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToFrontPage(ActionEvent event){ + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToInboxPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_inbox", event, null, null, authToken); + } + + @FXML + private void switchToHistoryPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_history", event, null, null, authToken); + } + + @FXML + private void switchToSettingsPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserSettingsController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserSettingsController.java new file mode 100644 index 0000000..89cbc7d --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/profileUser/profileUserSettingsController.java @@ -0,0 +1,218 @@ +package ntnu.systemutvikling.team6.controller.profileUser; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.stage.Stage; +import ntnu.systemutvikling.team6.controller.components.BaseController; +import ntnu.systemutvikling.team6.controller.components.LoaderScene; +import ntnu.systemutvikling.team6.controller.components.NavbarController; +import ntnu.systemutvikling.team6.database.DAO.UserDAO; +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.database.Readers.UserSelect; +import ntnu.systemutvikling.team6.models.user.*; +import ntnu.systemutvikling.team6.security.PasswordHasher; + +public class profileUserSettingsController extends BaseController { + @FXML private NavbarController navbarController; + @FXML private ComboBox languageComboBox; + @FXML private ComboBox themeComboBox; + @FXML private ToggleButton anonymousToggle; + @FXML private Label anonymousLabel; + + @FXML private TextField NameField; + @FXML private TextField EmailField; + @FXML private PasswordField PassWordField; + @FXML private TextField ConfirmPasswordField; + @FXML private Button ConfirmChangeSettings; + @FXML private Button ConfirmChangeSettings1; + + // Sidebar FXML variables + @FXML private Label nameLabel; + @FXML private Label shortNameLabel; + @FXML private Label shortNameLabel2; + @FXML private Button logoutButton; + + + + @Override + protected void authTokenisSet() { + if (!isLoggedin()){ + showAlert(Alert.AlertType.ERROR, "Not logged inn", "You need to be logged inn to donate."); + Platform.runLater(() -> { + Stage stage = (Stage) Stage.getWindows().stream() + .filter(w -> w.isShowing()) + .findFirst() + .orElse(null); + if (stage != null) { + LoaderScene.LoadScene("loginSite", stage, null, null, authToken); + } + }); + } + navbarController.setAuthToken(authToken); + populateFields(); + } + public void populateFields(){ + languageComboBox.getItems().addAll("English", "Norwegian"); + themeComboBox.getItems().addAll("Light mode", "Dark mode"); + + User user = authToken.getCurrentUser(); + Settings settings = user.getSettings(); + // Names + nameLabel.setText(user.getUsername()); + shortNameLabel.setText(user.getUsername().substring(0,2).toUpperCase().trim()); + shortNameLabel2.setText(user.getUsername().substring(0,2).toUpperCase().trim()); + + NameField.setText(user.getUsername()); + EmailField.setText(user.getEmail()); + + // SettingsPage Spesefic: + languageComboBox.setValue(settings.getLanguage() == Language.NORWEGIAN ? "Norwegian" : "English"); + themeComboBox.setValue(settings.isLightMode() ? "Light mode" : "Dark mode"); + anonymousToggle.setSelected(settings.isAnonymous()); + + boolean on = settings.isAnonymous(); + anonymousLabel.setText(on ? "On" : "Off"); + anonymousToggle.setStyle( + "-fx-background-color: " + (on ? "#2f8f8b" : "#ccc") + ";" + + "-fx-background-radius: 14; -fx-min-width: 32; -fx-min-height: 28;" + + "-fx-max-width: 52; -fx-max-height: 28;" + ); + } + + @FXML + private void handleAnonymousToggle(ActionEvent event) { + boolean on = anonymousToggle.isSelected(); + anonymousLabel.setText(on ? "On" : "Off"); + anonymousToggle.setStyle( + "-fx-background-color: " + (on ? "#2f8f8b" : "#ccc") + ";" + + "-fx-background-radius: 14; -fx-min-width: 32; -fx-min-height: 28;" + + "-fx-max-width: 52; -fx-max-height: 28;" + ); + } + + @FXML + private void handleNewProfile(ActionEvent event){ + String nameText = NameField.getText(); + String emailText = EmailField.getText(); + String password = PassWordField.getText(); + String confirmPassword = ConfirmPasswordField.getText(); + + if (nameText.isBlank() || emailText.isBlank() || password.isBlank() || confirmPassword.isBlank()) { + showAlert(Alert.AlertType.ERROR, "Empty input", "Please fill out all fields"); + return; + } + + if (emailText == null || emailText.isBlank() || !emailText.contains("@") || !emailText.contains(".")) { + showAlert(Alert.AlertType.ERROR, "Invalid Email", "Please enter a valid email"); + return; + } + + if (!password.equals(confirmPassword)) { + showAlert(Alert.AlertType.ERROR, "Mismatch of password", "Password do not match"); + return; + } + String hashPassword = new PasswordHasher().getHashPassword(password); + User newUserOnlyCredentials= new User(authToken.getCurrentUser().getId().toString(),nameText, emailText, hashPassword,"NORMAL_USER"); + + boolean updateSuccess; + DatabaseConnection conn = new DatabaseConnection(); + UserDAO userDataObject = new UserDAO(conn); + UserSelect userReaderObject = new UserSelect(conn); + try { + if (!emailText.equals(authToken.getCurrentUser().getEmail())) { + boolean isEmailTaken = userReaderObject.isEmailTaken(emailText); + if (!isEmailTaken) { + updateSuccess = userDataObject.updateUserDetails(newUserOnlyCredentials); + } else { + throw new IllegalArgumentException("Email Alreay taken"); + } + } else { + updateSuccess = userDataObject.updateUserDetails(newUserOnlyCredentials); + } + } catch (IllegalArgumentException e) { + showAlert(Alert.AlertType.ERROR, "Email already taken", "Email already taken by another user."); + return; + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (updateSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Settings updated", + "You have successfully changed your settings"); + authToken.getCurrentUser().setUsername(nameText); + authToken.getCurrentUser().setPassword(password); + authToken.getCurrentUser().setEmail(emailText); + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } else { + System.out.println("Something went wrong when updating Settings"); + } + + } + + @FXML + private void handleNewPreferences(ActionEvent event) { + String selectedLanguage = languageComboBox.getValue(); + String selectedTheme = themeComboBox.getValue(); + boolean isAnonymous = anonymousToggle.isSelected(); + + Settings updatedSettings = new Settings( + isAnonymous, + selectedLanguage.equals("Norwegian") ? Language.NORWEGIAN : Language.ENGLISH, + selectedTheme.equals("Light mode") + ); + + DatabaseConnection conn = new DatabaseConnection(); + UserDAO userDataObject = new UserDAO(conn); + boolean updateSettingsSuccess; + try { + updateSettingsSuccess = userDataObject.updateUserSettings(authToken.getCurrentUser(), updatedSettings); + } catch (Exception e) { + e.printStackTrace(); + showAlert(Alert.AlertType.ERROR, "Unexpected Error", "Unexpected error ocurred"); + return; + } + if (updateSettingsSuccess) { + showAlert( + Alert.AlertType.INFORMATION, + "Settings updated", + "You have successfully changed your settings"); + authToken.getCurrentUser().setSettings(updatedSettings); + LoaderScene.LoadScene("profile_user_settings", event, null, null, authToken); + } + } + + // Sidebar Methods + @FXML + private void handleLogout(ActionEvent event){ + authToken.logout(); + showAlert(Alert.AlertType.INFORMATION, "Logging out", "Logging out..."); + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToFrontPage(ActionEvent event){ + LoaderScene.LoadScene("FrontPage", event, null, null, authToken); + } + + @FXML + private void switchToInboxPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_inbox", event, null, null, authToken); + + } + + @FXML + private void switchToHistoryPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_history", event, null, null, authToken); + } + + @FXML + private void switchToInterestPage(ActionEvent event){ + LoaderScene.LoadScene("profile_user_interests", event, null, null, authToken); + } + +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/CharityUserDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/CharityUserDAO.java new file mode 100644 index 0000000..99d9de8 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/CharityUserDAO.java @@ -0,0 +1,67 @@ +package ntnu.systemutvikling.team6.database.DAO; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.Settings; +import ntnu.systemutvikling.team6.models.user.User; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class CharityUserDAO { + + private DatabaseConnection connection; + + public CharityUserDAO(DatabaseConnection connection) { + this.connection = connection; + } + public boolean updateCharityVanityName(Charity charity){ + Connection conn = null; + String sql = """ + UPDATE CharityVanity SET + charity_name = ? + WHERE UUID_charity = ?; + """; + try { + conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + + System.out.println(charity.getUUID().toString()); + ps.setString(1, charity.getName()); + ps.setString(2, charity.getUUID().toString()); + + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Something went wrong when updating ah"); + return false; + } + + } + public boolean updateCharityVanityDescription(Charity charity){ + Connection conn = null; + String sql = """ + UPDATE CharityVanity SET + description = ? + WHERE UUID_charity = ?; + """; + try { + conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + + System.out.println(charity.getUUID().toString()); + ps.setString(1, charity.getDescription()); + ps.setString(2, charity.getUUID().toString()); + + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Something went wrong when updating ah"); + return false; + } + + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/DonationDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/DonationDAO.java index 1726870..dbcdf38 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/DonationDAO.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/DonationDAO.java @@ -4,6 +4,7 @@ import java.util.UUID; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Donation; import ntnu.systemutvikling.team6.models.user.User; /** @@ -24,21 +25,22 @@ public DonationDAO(DatabaseConnection connection) { * @param charity * @param amount */ - public void addDonation(Charity charity, User user, double amount) { + public void addDonation(Donation donation) { String sql_query = """ - INSERT INTO Donations (UUID_Donations, amount, date, charity_id, user_id) - VALUES (?, ?, ?, ?, ?) + INSERT INTO Donations (UUID_Donations, amount, isAnonymous, date, charity_id, user_id) + VALUES (?, ?, ?, ?, ?, ?) """; try (Connection conn = connection.getMySqlConnection(); PreparedStatement ps = conn.prepareStatement(sql_query)) { conn.setAutoCommit(false); - ps.setString(1, UUID.randomUUID().toString()); - ps.setDouble(2, amount); - ps.setDate(3, new Date(System.currentTimeMillis())); - ps.setString(4, charity.getUUID().toString()); - ps.setString(5, user.getId().toString()); + ps.setString(1, donation.getDonationID().toString()); + ps.setDouble(2, donation.getAmount()); + ps.setBoolean(3, donation.getDonor().getSettings().isAnonymous()); + ps.setDate(4, Date.valueOf(donation.getDate())); + ps.setString(5, donation.getCharity().getUUID().toString()); + ps.setString(6, donation.getDonor().getId().toString()); ps.executeUpdate(); conn.commit(); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FavouritesDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FavouritesDAO.java new file mode 100644 index 0000000..0f6fd2d --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FavouritesDAO.java @@ -0,0 +1,132 @@ +package ntnu.systemutvikling.team6.database.DAO; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; +import ntnu.systemutvikling.team6.models.user.User; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class FavouritesDAO { + + private final DatabaseConnection connection; + + public FavouritesDAO(DatabaseConnection connection) { + this.connection = connection; + } + + public boolean isFavourite(User user, Charity charity) { + String sql = "SELECT * FROM User_has_favourites WHERE Favourer = ? AND Favourite_Charity = ?"; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql)) { + + ps.setString(1, user.getId().toString()); + ps.setString(2, charity.getUUID().toString()); + + ResultSet rs = ps.executeQuery(); + return rs.next(); + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + public boolean addFavourite(User user, Charity charity) { + String sql = "INSERT INTO User_has_favourites (Favourer, Favourite_charity) VALUES (?, ?)"; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql)) { + + ps.setString(1, user.getId().toString()); + ps.setString(2, charity.getUUID().toString()); + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + public boolean removeFavourite(User user, Charity charity) { + String sql = "DELETE FROM User_has_favourites WHERE Favourer = ? AND Favourite_charity = ?"; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql)) { + + ps.setString(1, user.getId().toString()); + ps.setString(2, charity.getUUID().toString()); + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + public List getFavouritesForUser(String user_id) { + CharityRegistry registry = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + uf.Favourite_Charity, + c.UUID_charities, c.org_number, c.pre_approved, c.status, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + cat.category + FROM User_has_favourites uf + INNER JOIN Charities c ON uf.Favourite_Charity = c.UUID_charities + INNER JOIN CharityVanity cv ON uf.Favourite_Charity = cv.UUID_charity + LEFT JOIN Charity_Categories cc ON cc.Charities_UUID_charities = c.UUID_charities + LEFT JOIN Categories cat ON cat.category_id = cc.Categories_category_id + WHERE Favourer = ?; + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, user_id); + ResultSet rs = stmt.executeQuery(); + + + Charity currentCharity = null; + + registry = new CharityRegistry(); + while (rs.next()) { + String currentId = rs.getString("UUID_charities"); + if (currentCharity == null || !currentId.equals(currentCharity.getUUID().toString())) { + System.out.println("Adding Charities"); + currentCharity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB")); + registry.addCharity(currentCharity); + } + + String categoryName = rs.getString("category"); + if (categoryName != null & !currentCharity.getCategory().contains(categoryName)) { + currentCharity.getCategory().add(categoryName); + } + + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating."); + } finally { + conn = null; + } + return registry.getAllCharities(); + } + +} \ No newline at end of file diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FeedbackDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FeedbackDAO.java new file mode 100644 index 0000000..705929a --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/FeedbackDAO.java @@ -0,0 +1,44 @@ +package ntnu.systemutvikling.team6.database.DAO; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Feedback; + +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class FeedbackDAO { + private final DatabaseConnection connection; + + public FeedbackDAO(DatabaseConnection connection){ + this.connection = connection; + } + + public boolean addFeedbackToCharity(Feedback feedback, Charity toCharity){ + String sql = """ + INSERT INTO Feedback + (UUID_feedback, feedback_comment, feedback_date, isAnonymous, charity_id, user_id) + VALUES (?, ?, ?, ?, ?, ?); + + """; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql)) { + + ps.setString(1, feedback.getFeedbackId().toString()); + ps.setString(2, feedback.getComment()); + ps.setDate(3, Date.valueOf(feedback.getDate())); + ps.setBoolean(4, feedback.getUser().getSettings().isAnonymous()); + ps.setString(5, toCharity.getUUID().toString()); + ps.setString(6, feedback.getUser().getId().toString()); + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/MessageDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/MessageDAO.java new file mode 100644 index 0000000..8545863 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/MessageDAO.java @@ -0,0 +1,77 @@ +package ntnu.systemutvikling.team6.database.DAO; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.user.Message; + +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class MessageDAO { + private final DatabaseConnection connection; + + public MessageDAO(DatabaseConnection connection){ + this.connection = connection; + } + public boolean addMessage(Message message){ + // First fetch all unique donors for this charity + List donorIds = getDonorIdsForCharity(message.getFrom().getUUID().toString()); + + if (donorIds.isEmpty()) return false; + String sql = """ + INSERT INTO Messages + (UUID_message, message_title, message_content, message_date, sender_charity_id, user_id) + VALUES (?, ?, ?, ?, ?, ?) + """; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + + for (String donorId : donorIds) { + stmt.setString(1, UUID.randomUUID().toString()); + stmt.setString(2, message.getTitle()); + stmt.setString(3, message.getContent()); + stmt.setDate(4, Date.valueOf(message.getTimeAndDate())); + stmt.setString(5, message.getFrom().getUUID().toString()); + stmt.setString(6, donorId); + stmt.addBatch(); + } + + int[] results = stmt.executeBatch(); + return results.length > 0; + + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Failed to send messages to donors."); + } + } + + private List getDonorIdsForCharity(String charityId) { + List donorIds = new ArrayList<>(); + String sql = """ + SELECT DISTINCT user_id + FROM Donations + WHERE charity_id = ? + """; + + try (Connection conn = connection.getMySqlConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + + stmt.setString(1, charityId); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + donorIds.add(rs.getString("user_id")); + } + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Failed to fetch donor IDs."); + } + return donorIds; + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/UserDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/UserDAO.java index 7929da7..2357894 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/UserDAO.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DAO/UserDAO.java @@ -4,6 +4,7 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.user.Settings; import ntnu.systemutvikling.team6.models.user.User; /** @@ -32,19 +33,18 @@ public boolean registerUser(User user) { """ INSERT INTO User ( UUID_User, - user_displayname, user_name, user_email, user_password, role ) - VALUES (?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?) """; String settingsSql = """ INSERT INTO Settings ( - User_UUID_User, + UUID_user, isAnonymous, language, lightmode @@ -62,11 +62,10 @@ INSERT INTO Settings ( try (PreparedStatement psUser = conn.prepareStatement(userSql)) { psUser.setString(1, user.getId().toString()); - psUser.setString(2, user.getDisplayName()); // display name - psUser.setString(3, user.getUsername()); // username - psUser.setString(4, user.getEmail()); - psUser.setString(5, user.getPasswordHash()); - psUser.setString(6, user.getRole().name()); + psUser.setString(2, user.getUsername()); + psUser.setString(3, user.getEmail()); + psUser.setString(4, user.getPasswordHash()); + psUser.setString(5, user.getRole().name()); psUserRows = psUser.executeUpdate(); } @@ -89,4 +88,60 @@ INSERT INTO Settings ( return false; } } + + public boolean updateUserSettings(User user, Settings settings){ + Connection conn = null; + String sql = """ + UPDATE Settings SET + isAnonymous = ?, + language = ?, + lightmode = ? + WHERE UUID_user = ?; + """; + try { + conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + + ps.setBoolean(1, settings.isAnonymous()); + ps.setString(2, settings.getLanguage().name()); + ps.setBoolean(3, settings.isLightMode()); + ps.setString(4, user.getId().toString()); + + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Something went wrong when updating Settings"); + return false; + } + + } + + public boolean updateUserDetails(User user){ + Connection conn = null; + String sql = """ + UPDATE User SET + user_name = ?, + user_email = ?, + user_password = ? + WHERE UUID_User = ?; + """; + try { + conn = connection.getMySqlConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + + ps.setString(1, user.getUsername()); + ps.setString(2, user.getEmail()); + ps.setString(3, user.getPasswordHash()); + ps.setString(4, user.getId().toString()); + + return ps.executeUpdate() > 0; + + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Something went wrong when updating Settings"); + return false; + } + + } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java index 6fdcc88..4b138de 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java @@ -99,7 +99,6 @@ FOREIGN KEY (`user_id`) -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `apbaluna`.`User` ( `UUID_User` CHAR(36) NOT NULL, - `user_displayname` VARCHAR(255) NOT NULL, `user_name` VARCHAR(255) NOT NULL, `user_email` VARCHAR(255) NOT NULL, `user_password` VARCHAR(255) NOT NULL, @@ -233,23 +232,23 @@ FOREIGN KEY (`Charities_UUID_charities`) -- ----------------------------------------------------- -- Table `apbaluna`.`CharityUsers` -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`CharityUsers` ( - `Charities_UUID_charities` CHAR(36) NOT NULL, - `User_UUID_User` CHAR(36) NOT NULL, - PRIMARY KEY (`Charities_UUID_charities`, `User_UUID_User`), - INDEX `fk_Charities_has_User_User1_idx` (`User_UUID_User` ASC) VISIBLE, - INDEX `fk_Charities_has_User_Charities1_idx` (`Charities_UUID_charities` ASC) VISIBLE, - CONSTRAINT `fk_Charities_has_User_Charities1` - FOREIGN KEY (`Charities_UUID_charities`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Charities_has_User_User1` - FOREIGN KEY (`User_UUID_User`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; + CREATE TABLE IF NOT EXISTS `apbaluna`.`CharityUsers` ( + `TheCharity` CHAR(36) NOT NULL, + `CharityUserId` CHAR(36) NOT NULL, + PRIMARY KEY (`TheCharity`, `CharityUserId`), + INDEX `fk_Charities_has_User_User1_idx` (`CharityUserId` ASC) VISIBLE, + INDEX `fk_Charities_has_User_Charities1_idx` (`TheCharity` ASC) VISIBLE, + CONSTRAINT `fk_Charities_has_User_Charities1` + FOREIGN KEY (`TheCharity`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Charities_has_User_User1` + FOREIGN KEY (`CharityUserId`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; """; String charityVanityTable = """ @@ -271,6 +270,30 @@ FOREIGN KEY (`UUID_charity`) ENGINE = InnoDB; """; + String userHasFavourites = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`User_has_favourites` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`User_has_favourites` ( + `Favourite_Charity` CHAR(36) NOT NULL, + `Favourer` CHAR(36) NOT NULL, + PRIMARY KEY (`Favourite_Charity`, `Favourer`), + INDEX `fk_Charities_has_User_User2_idx` (`Favourer` ASC) VISIBLE, + INDEX `fk_Charities_has_User_Charities2_idx` (`Favourite_Charity` ASC) VISIBLE, + CONSTRAINT `fk_Charities_has_User_Charities2` + FOREIGN KEY (`Favourite_Charity`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Charities_has_User_User2` + FOREIGN KEY (`Favourer`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + try (Connection conn = connection.getMySqlConnection(); Statement s = conn.createStatement()) { @@ -284,6 +307,8 @@ FOREIGN KEY (`UUID_charity`) s.execute(charityCategoriesTable); s.execute(charityUserTable); s.execute(charityVanityTable); + s.execute(userHasFavourites); + } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("Error creating table."); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java index e863cac..640d90c 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java @@ -58,21 +58,20 @@ public CharityRegistry getCharitiesFromDB() { String sql_query = """ - SELECT - c.UUID_charities, c.org_number, c.pre_approved, c.status, - f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, - cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, - u.UUID_user, u.user_displayname, u.user_name, u.user_email, u.user_password, u.role, - cat.category - FROM Charities c - LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities - LEFT JOIN User u ON f.user_id = u.UUID_user - LEFT JOIN Charity_Categories cc ON cc.Charities_UUID_charities = c.UUID_charities - LEFT JOIN Categories cat ON cat.category_id = cc.Categories_category_id - INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities - ORDER BY c.UUID_charities; - """; - + SELECT + c.UUID_charities, c.org_number, c.pre_approved, c.status, + f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + u.UUID_user, u.user_name, u.user_email, u.user_password, u.role, + cat.category + FROM Charities c + LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities + LEFT JOIN User u ON f.user_id = u.UUID_user + LEFT JOIN Charity_Categories cc ON cc.Charities_UUID_charities = c.UUID_charities + LEFT JOIN Categories cat ON cat.category_id = cc.Categories_category_id + INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities; + ORDER BY c.UUID_charities; + """; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql_query); @@ -107,13 +106,8 @@ public CharityRegistry getCharitiesFromDB() { } String categoryName = rs.getString("category"); - - if (categoryName != null) { - categoryName = categoryName.toLowerCase().trim(); - - if (!categoryName.isEmpty() && !currentCharity.getCategory().contains(categoryName)) { - currentCharity.getCategory().add(categoryName); - } + if (categoryName != null & !currentCharity.getCategory().contains(categoryName)) { + currentCharity.getCategory().add(categoryName); } String feedbackId = rs.getString("UUID_feedback"); @@ -124,7 +118,6 @@ public CharityRegistry getCharitiesFromDB() { User userWithMinimalSettingsAndInbox = new User( rs.getString("UUID_User"), - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), @@ -175,9 +168,11 @@ public ArrayList getFeedbackforCharityUUID(String charity_uuid) { """ SELECT f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, - u.UUID_user, u.user_displayname, u.user_name, u.user_email, u.user_password, u.role + u.UUID_user, u.user_name, u.user_email, u.user_password, u.role, + s.language, s.lightmode FROM Feedback f LEFT JOIN User u ON f.user_id = u.UUID_user + RIGHT JOIN Settings s ON u.UUID_user = s.UUID_user WHERE f.charity_id = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); @@ -188,12 +183,15 @@ public ArrayList getFeedbackforCharityUUID(String charity_uuid) { User userWithSettingsAndNoInbox = new User( rs.getString("UUID_User"), - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), rs.getString("role")); - userWithSettingsAndNoInbox.setSettings(new Settings(false, Language.NORWEGIAN, false)); + userWithSettingsAndNoInbox.setSettings(new Settings( + rs.getBoolean("isAnonymous"), + Language.valueOf(rs.getString("language")), + rs.getBoolean("lightmode") + )); Feedback feedback = new Feedback( rs.getString("UUID_feedback"), diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java index f975488..a577880 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java @@ -1,9 +1,7 @@ package ntnu.systemutvikling.team6.database.Readers; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; + import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.Donation; @@ -59,7 +57,7 @@ public DonationRegistry getDonationFromDB() { SELECT d.UUID_Donations, d.amount, d.isAnonymous, d.date, d.charity_id, d.user_id, c.UUID_charities, c.org_number, c.pre_approved, c.status, - u.UUID_User, u.user_displayname, u.user_name, u.user_email, u.user_password, u.role + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role FROM Donations d INNER JOIN Charities c ON d.charity_id = c.UUID_charities INNER JOIN User u ON d.user_id = u.UUID_user @@ -79,7 +77,6 @@ public DonationRegistry getDonationFromDB() { User user = new User( rs.getString("UUID_User"), - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), @@ -100,4 +97,122 @@ public DonationRegistry getDonationFromDB() { } return registry; } + public DonationRegistry getDonationForUser(String uuid) { + DonationRegistry registry = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + d.UUID_Donations, d.amount, d.isAnonymous, d.date, d.charity_id, d.user_id, + c.UUID_charities, c.org_number, c.pre_approved, c.status, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role + FROM Donations d + INNER JOIN Charities c ON d.charity_id = c.UUID_charities + INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities + INNER JOIN User u ON d.user_id = u.UUID_user + WHERE d.user_id = ? + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, uuid); + ResultSet rs = stmt.executeQuery(); + + registry = new DonationRegistry(); + while (rs.next()) { + Charity charity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB")); + User user = + new User( + rs.getString("UUID_User"), + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role")); + Donation donation = + new Donation( + rs.getString("UUID_Donations"), + rs.getDouble("amount"), + rs.getDate("date").toLocalDate(), + charity, + user, + rs.getBoolean("isAnonymous")); + registry.addDonation(donation); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return registry; + } + public DonationRegistry getDonationForCharity(String uuid) { + DonationRegistry registry = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + d.UUID_Donations, d.amount, d.isAnonymous, d.date, d.charity_id, d.user_id, + c.UUID_charities, c.org_number, c.pre_approved, c.status, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role + FROM Donations d + INNER JOIN Charities c ON d.charity_id = c.UUID_charities + INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities + INNER JOIN User u ON d.user_id = u.UUID_user + WHERE c.UUID_charities = ? + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, uuid); + ResultSet rs = stmt.executeQuery(); + + registry = new DonationRegistry(); + while (rs.next()) { + Charity charity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB")); + User user = + new User( + rs.getString("UUID_User"), + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role")); + Donation donation = + new Donation( + rs.getString("UUID_Donations"), + rs.getDouble("amount"), + rs.getDate("date").toLocalDate(), + charity, + user, + rs.getBoolean("isAnonymous")); + registry.addDonation(donation); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return registry; + } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java index 6956dc5..bc5da17 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java @@ -2,8 +2,13 @@ import java.sql.*; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.models.registry.UserRegistry; import ntnu.systemutvikling.team6.models.user.*; import ntnu.systemutvikling.team6.security.PasswordHasher; @@ -30,20 +35,23 @@ public UserSelect(DatabaseConnection connection) { this.connection = connection; } - public boolean isUsernameTaken(String username) { - try (Connection conn = connection.getMySqlConnection(); - Statement stmt = conn.createStatement()) { + public boolean isEmailTaken(String email){ + if (email == null || email.isBlank() || !email.contains("@") || !email.contains(".")) { + throw new IllegalArgumentException( + "Email cannot be null or blank," + " and must contain '@' and '.'"); + } + try (Connection conn = connection.getMySqlConnection()) { String mysql = - """ - SELECT UUID_User FROM User WHERE user_name = ? + """ + SELECT UUID_User FROM User WHERE user_email = ? """; PreparedStatement statement = conn.prepareStatement(mysql); - statement.setString(1, username); + statement.setString(1, email); ResultSet rs = statement.executeQuery(); if (rs.next()) { - System.out.println("Username Taken already"); + System.out.println("Email Taken already"); return true; } @@ -53,6 +61,66 @@ public boolean isUsernameTaken(String username) { return false; } + public Charity getUserCharityUser(String uuid){ + if (uuid == null || uuid.isBlank()) { + throw new IllegalArgumentException( + "UUID cannot be null or blank"); + } + Charity currentCharity = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + c.UUID_charities, c.org_number, c.pre_approved, c.status, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + cat.category + FROM CharityUsers cu + INNER JOIN Charities c ON c.UUID_charities = cu.TheCharity + INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities + LEFT JOIN Charity_Categories cc ON cc.Charities_UUID_charities = c.UUID_charities + LEFT JOIN Categories cat ON cat.category_id = cc.Categories_category_id + WHERE CharityUserId = ? + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, uuid); + ResultSet rs = stmt.executeQuery(); + + String lastCharity = null; + + while (rs.next()) { + String currentId = rs.getString("UUID_charities"); + if (lastCharity == null || !currentId.equals(lastCharity)) { + currentCharity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB")); + lastCharity = currentId; + } + + String categoryName = rs.getString("category"); + if (categoryName != null && !currentCharity.getCategory().contains(categoryName)) { + currentCharity.getCategory().add(categoryName); + } + } + + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return currentCharity; + } + + /** * Retrieves a single {@link User} from the database matching the given username and password. * @@ -65,13 +133,13 @@ public boolean isUsernameTaken(String username) { * user_password}; the {@code user_name} column is not yet included in the WHERE clause, which may * be a bug. * - * @param username the plain-text username to look up + * @param email the email to look up * @param password the plain-text password; hashed internally before the query runs * @return the matching {@link User} with settings and inbox populated, or {@code null} if no * match is found * @throws RuntimeException if a {@link SQLException} occurs while executing the query */ - public User getUserFromDBUsernameAndPassword(String username, String password) { + public User getUserFromDBEmailAndPassword(String email, String password) { PasswordHasher hasher = new PasswordHasher(); String hashedpassword = hasher.getHashPassword(password); @@ -82,28 +150,38 @@ public User getUserFromDBUsernameAndPassword(String username, String password) { String sql_query = """ SELECT - u.UUID_User, u.user_displayname, u.user_name, u.user_email, u.user_password, u.role, - s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, - m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, + s.UUID_user, s.isAnonymous, s.language, s.lightmode, + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + c.UUID_charities, c.org_number, c.pre_approved, c.status FROM User u - LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user + LEFT JOIN Settings s ON u.UUID_User = s.UUID_user LEFT JOIN Messages m ON u.UUID_User = m.user_id - WHERE u.user_name = ? AND u.user_password = ?; + LEFT JOIN Charities c ON m.sender_charity_id = c.UUID_charities + LEFT JOIN CharityVanity cv ON c.UUID_charities = cv.UUID_charity + WHERE u.user_email = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); - stmt.setString(1, username); - stmt.setString(2, hashedpassword); + stmt.setString(1, email); - ResultSet rs = stmt.executeQuery(); - String lastUserid = null; + + ResultSet rs = stmt.executeQuery(); + HashSet addedMessageIds = new HashSet<>(); while (rs.next()) { String userId = rs.getString("UUID_User"); - if (lastUserid == null || !userId.equals(lastUserid)) { + System.out.println(rs.getString("user_name")); + + if (user == null) { + String storedHash = rs.getString("user_password"); + + if (!new PasswordHasher().isValidPassword(password, storedHash)){ + return null; + } user = new User( userId, - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), @@ -117,18 +195,36 @@ public User getUserFromDBUsernameAndPassword(String username, String password) { user.setSettings(settings); } user.setInbox(new Inbox()); - lastUserid = userId; } String messageId = rs.getString("UUID_message"); - if (messageId != null) { - Message message = - new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date"))); + if (messageId != null && !addedMessageIds.contains(messageId)) { + addedMessageIds.add(messageId); + Charity fromCharity = null; + String charityId = rs.getString("UUID_charities"); + if (charityId != null) { + fromCharity = new Charity( + charityId, + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB") + ); + } - user.getInbox().addMessage(message); + if (fromCharity != null) { + Message message = new Message( + rs.getString("message_title"), + fromCharity, + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + user.getInbox().addMessage(message); + } } } } catch (SQLException e) { @@ -160,12 +256,16 @@ public User getUserFromDBUuid(String user_id) { String sql_query = """ SELECT - u.UUID_User, u.user_displayname u.user_name, u.user_email, u.user_password, u.role, - s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, - m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, + s.UUID_user, s.isAnonymous, s.language, s.lightmode, + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + c.UUID_charities, c.org_number, c.pre_approved, c.status FROM User u - LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user + LEFT JOIN Settings s ON u.UUID_User = s.UUID_user LEFT JOIN Messages m ON u.UUID_User = m.user_id + LEFT JOIN Charities c ON m.sender_charity_id = c.UUID_charities + LEFT JOIN CharityVanity cv ON c.UUID_charities = cv.UUID_charity WHERE u.UUID_User = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); @@ -173,13 +273,13 @@ public User getUserFromDBUuid(String user_id) { ResultSet rs = stmt.executeQuery(); String lastUserid = null; + HashSet addedMessageIds = new HashSet<>(); while (rs.next()) { String userId = rs.getString("UUID_User"); if (lastUserid == null || !userId.equals(lastUserid)) { user = new User( userId, - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), @@ -196,15 +296,34 @@ public User getUserFromDBUuid(String user_id) { lastUserid = userId; } String messageId = rs.getString("UUID_message"); - if (messageId != null) { - Message message = - new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date"))); + if (messageId != null && !addedMessageIds.contains(messageId)) { + addedMessageIds.add(messageId); + Charity fromCharity = null; + String charityId = rs.getString("UUID_charities"); + if (charityId != null) { + fromCharity = new Charity( + charityId, + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB") + ); + } - user.getInbox().addMessage(message); + if (fromCharity != null) { + Message message = new Message( + rs.getString("message_title"), + fromCharity, + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + user.getInbox().addMessage(message); + } } } } catch (SQLException e) { @@ -236,18 +355,23 @@ public UserRegistry getUsersFromDB() { String sql_query = """ SELECT - u.UUID_User, u.user_displayname u.user_name, u.user_email, u.user_password, u.role, - s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, - m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, + s.UUID_user, s.isAnonymous, s.language, s.lightmode, + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + c.UUID_charities, c.org_number, c.pre_approved, c.status FROM User u - LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user + LEFT JOIN Settings s ON u.UUID_User = s.UUID_user LEFT JOIN Messages m ON u.UUID_User = m.user_id + LEFT JOIN Charities c ON m.sender_charity_id = c.UUID_charities + LEFT JOIN CharityVanity cv ON c.UUID_charities = cv.UUID_charity """; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql_query); User currentUser = null; String lastUserid = null; + HashSet addedMessageIds = new HashSet<>(); while (rs.next()) { String userId = rs.getString("UUID_User"); @@ -256,7 +380,6 @@ public UserRegistry getUsersFromDB() { currentUser = new User( userId, - rs.getString("user_displayname"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), @@ -274,15 +397,34 @@ public UserRegistry getUsersFromDB() { lastUserid = userId; } String messageId = rs.getString("UUID_message"); - if (messageId != null) { - Message message = - new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date"))); + if (messageId != null && !addedMessageIds.contains(messageId)) { + addedMessageIds.add(messageId); + Charity fromCharity = null; + String charityId = rs.getString("UUID_charities"); + if (charityId != null) { + fromCharity = new Charity( + charityId, + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB") + ); + } - currentUser.getInbox().addMessage(message); + if (fromCharity != null) { + Message message = new Message( + rs.getString("message_title"), + fromCharity, + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + currentUser.getInbox().addMessage(message); + } } } } catch (SQLException e) { @@ -312,7 +454,7 @@ public Settings getSettingsForUser(String user_id) { conn = connection.getMySqlConnection(); String sql_query = """ - SELECT User_UUID_User, isAnonymous, language, lightmode FROM Settings + SELECT UUID_user, isAnonymous, language, lightmode FROM Settings WHERE UUID_user = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); @@ -355,7 +497,13 @@ public Inbox getInboxForUser(String user_id) { conn = connection.getMySqlConnection(); String sql_query = """ - SELECT UUID_message, message_title, message_content, message_date, sender_user_id, sender_charity_id, user_id FROM Messages + SELECT + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + c.UUID_charities, c.org_number, c.pre_approved, c.status + FROM Messages m + LEFT JOIN Charities c ON m.sender_charity_id = c.UUID_charities + LEFT JOIN CharityVanity cv ON c.UUID_charities = cv.UUID_charity WHERE user_id = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); @@ -363,13 +511,32 @@ public Inbox getInboxForUser(String user_id) { ResultSet rs = stmt.executeQuery(); while (rs.next()) { - Message message = - new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date"))); - inbox.addMessage(message); + Charity fromCharity = null; + String charityId = rs.getString("UUID_charities"); + if (charityId != null) { + fromCharity = new Charity( + charityId, + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), + rs.getBoolean("pre_approved"), + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB") + ); + } + + if (fromCharity != null) { + Message message = new Message( + rs.getString("message_title"), + fromCharity, + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + inbox.addMessage(message); + } } } catch (SQLException e) { e.printStackTrace(); @@ -379,4 +546,6 @@ public Inbox getInboxForUser(String user_id) { } return inbox; } + + } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java index 8bf310f..4516abb 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java @@ -169,6 +169,11 @@ public byte[] getLogoBlob() { return this.logoBlob; } + /** Setter for new name */ + public void setName(String name) { + this.name = name; + } + /** Setter for verification status. This one sets the charity as verified. */ public void setVerified() { this.status = "approved"; diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Message.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Message.java index 3a2a75d..9a2e07c 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Message.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Message.java @@ -1,5 +1,7 @@ package ntnu.systemutvikling.team6.models.user; +import ntnu.systemutvikling.team6.models.Charity; + import java.time.LocalDate; import java.util.UUID; @@ -13,26 +15,26 @@ public class Message { private final UUID id; private final String title; - private final UUID fromCharityID; + private final Charity fromCharity; private final String content; private final LocalDate timeAndDate; /** - * Creates a message with a unique identifier. The message includes a title, a string who it's + * Creates a message with a unique identifier. The message includes a title, the Charity who it's * from, content and the time and date. * * @param title the title of the message - * @param from who the message is from + * @param charity who the message is from * @param content the content of the message * @throws IllegalArgumentException if title, from or content is null or blank. */ - public Message(String title, UUID from, String content) { + public Message(String title, Charity charity, String content) { if (title == null || title.isBlank()) { throw new IllegalArgumentException("Title cannot be null or blank."); } - if (from == null) { + if (charity == null) { throw new IllegalArgumentException("From cannot be null or blank."); } @@ -42,7 +44,7 @@ public Message(String title, UUID from, String content) { this.id = UUID.randomUUID(); this.title = title; - this.fromCharityID = from; + this.fromCharity = charity; this.content = content; this.timeAndDate = LocalDate.now(); } @@ -52,18 +54,18 @@ public Message(String title, UUID from, String content) { * from, content and the time and date. This one creates a message that has been created before. * * @param title the title of the message - * @param from who the message is from + * @param charity who the message is from * @param content the content of the message * @param date date of when the message was created * @throws IllegalArgumentException if title, from or content is null or blank. */ - public Message(String title, UUID from, String content, LocalDate date) { + public Message(String title, Charity charity, String content, LocalDate date) { if (title == null || title.isBlank()) { throw new IllegalArgumentException("Title cannot be null or blank."); } - if (from == null) { + if (charity == null) { throw new IllegalArgumentException("From cannot be null or blank."); } @@ -77,7 +79,7 @@ public Message(String title, UUID from, String content, LocalDate date) { this.id = UUID.randomUUID(); this.title = title; - this.fromCharityID = from; + this.fromCharity = charity; this.content = content; this.timeAndDate = date; } @@ -90,8 +92,8 @@ public String getTitle() { return title; } - public UUID getFrom() { - return fromCharityID; + public Charity getFrom() { + return fromCharity; } public String getContent() { diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Role.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Role.java index 94e0b22..c68752d 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Role.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Role.java @@ -8,4 +8,5 @@ public enum Role { NORMAL_USER, CHARITY_USER, + ADMIN, } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/User.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/User.java index 5d76755..20e1663 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/User.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/User.java @@ -17,7 +17,6 @@ public class User { private static final PasswordHasher passwordHasher = new PasswordHasher(); private final UUID id; - private String displayName; private String username; private String email; private String passwordHash; @@ -28,7 +27,6 @@ public class User { /** * Creates a new user. * - * @param displayName the name of the user that is shown * @param username unqiue username used for login * @param email the email of the user * @param password the password for the user @@ -37,18 +35,7 @@ public class User { * @param inbox the user´s inbox * @throws IllegalArgumentException if any required argument is invalid. */ - public User( - String displayName, - String username, - String email, - String password, - Role role, - Settings settings, - Inbox inbox) { - if (displayName == null || displayName.isBlank()) { - throw new IllegalArgumentException("displayName cannot be null or blank."); - } - + public User(String username, String email, String password, Role role, Settings settings, Inbox inbox) { if (username == null || username.isBlank()) { throw new IllegalArgumentException("Name cannot be null or blank."); } @@ -71,7 +58,6 @@ public User( } this.id = UUID.randomUUID(); - this.displayName = displayName; this.username = username; this.email = email; this.passwordHash = passwordHasher.getHashPassword(password); @@ -85,20 +71,13 @@ public User( * later date throught another method in databaseManager class * * @param uuid gives the user a unique identifier with UUID - * @param displayName the name of the user that is shown * @param username the name of the user * @param email the email of the user * @param password the password for the user * @param role users role * @throws IllegalArgumentException if any required argument is invalid. */ - public User( - String uuid, - String displayName, - String username, - String email, - String password, - String role) { + public User(String uuid, String username, String email, String password, String role) { if (uuid == null || uuid.isBlank()) { throw new IllegalArgumentException("UUID cannot be null or blank."); @@ -118,7 +97,6 @@ public User( } this.id = UUID.fromString(uuid); - this.displayName = displayName; this.username = username; this.email = email; this.passwordHash = password; @@ -133,10 +111,6 @@ public UUID getId() { return id; } - public String getDisplayName() { - return displayName; - } - public String getUsername() { return username; } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/AuthenticationService.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/AuthenticationService.java index b2ee203..cd9cbc2 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/AuthenticationService.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/AuthenticationService.java @@ -2,111 +2,123 @@ import ntnu.systemutvikling.team6.database.DAO.UserDAO; import ntnu.systemutvikling.team6.database.Readers.UserSelect; +import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.user.Inbox; import ntnu.systemutvikling.team6.models.user.Role; import ntnu.systemutvikling.team6.models.user.Settings; import ntnu.systemutvikling.team6.models.user.User; + /** - * Service class responsible for handling user authentication operations, including login, - * registration, and logout functionality. - * - *

Maintains the state of the currently authenticated user throughout the session. + * Service class responsible for handling user authentication operations, + * including login, registration, and logout functionality. + *

+ * Maintains the state of the currently authenticated user throughout the session. + *

*/ public class AuthenticationService { - /** Handles read operations for user data from the database. */ - private final UserSelect userDataReader; - - /** Handles write operations for user data to the database. */ - private final UserDAO userDataSender; - - /** The currently authenticated user, or {@code null} if no user is logged in. */ - private User currentUser; - - /** - * Constructs an {@code AuthenticationService} with the specified data access objects. - * - * @param userDataReader the data reader used to query user information from the database - * @param userDataSender the DAO used to persist new user registrations to the database - */ - public AuthenticationService(UserSelect userDataReader, UserDAO userDataSender) { - this.userDataReader = userDataReader; - this.userDataSender = userDataSender; - } - - /** - * Attempts to authenticate a user with the given credentials. - * - *

If a matching user is found in the database, they are set as the current user and the method - * returns {@code true}. - * - * @param username the username of the user attempting to log in - * @param password the password of the user attempting to log in - * @return {@code true} if authentication was successful; {@code false} otherwise - */ - public boolean login(String username, String password) { - User user = userDataReader.getUserFromDBUsernameAndPassword(username, password); - - if (user != null) { - currentUser = user; - return true; + /** Handles read operations for user data from the database. */ + private final UserSelect userDataReader; + /** Handles write operations for user data to the database. */ + private final UserDAO userDataSender; + + /** The currently authenticated user, or {@code null} if no user is logged in. */ + private User currentUser; + + private Charity isCharityUser; + + /** + * Constructs an {@code AuthenticationService} with the specified data access objects. + * + * @param userDataReader the data reader used to query user information from the database + * @param userDataSender the DAO used to persist new user registrations to the database + */ + public AuthenticationService(UserSelect userDataReader, UserDAO userDataSender) { + this.userDataReader = userDataReader; + this.userDataSender = userDataSender; + } + + /** + * Attempts to authenticate a user with the given credentials. + *

+ * If a matching user is found in the database, they are set as the current user + * and the method returns {@code true}. + *

+ * + * @param email the username of the user attempting to log in + * @param password the password of the user attempting to log in + * @return {@code true} if authentication was successful; {@code false} otherwise + */ + public boolean login(String email, String password){ + User user = userDataReader.getUserFromDBEmailAndPassword(email, password); + + if (user != null){ + currentUser = user; + isCharityUser = userDataReader.getUserCharityUser(currentUser.getId().toString()); + System.out.println("User gotten"); + return true; + } + + return false; } - return false; - } - - /** - * Registers a new user account with the provided details. - * - *

The new user is assigned the {@link Role#NORMAL_USER} role and default {@link Settings} and - * {@link Inbox}. Registration will fail if the username is already taken or if the database - * operation is unsuccessful. On success, the new user is set as the current user. - * - * @param displayName the display name shown on the user's profile - * @param username the unique username for the new account - * @param email the email address associated with the new account - * @param password the password for the new account - * @return {@code true} if registration was successful; {@code false} if the username is already - * taken or the database operation failed - */ - public boolean register(String displayName, String username, String email, String password) { - User newUser = - new User( - displayName, username, email, password, Role.NORMAL_USER, new Settings(), new Inbox()); - - if (userDataReader.isUsernameTaken(username)) { - return false; + /** + * Registers a new user account with the provided details. + *

+ * The new user is assigned the {@link Role#NORMAL_USER} role and default + * {@link Settings} and {@link Inbox}. Registration will fail if the + * username is already taken or if the database operation is unsuccessful. + * On success, the new user is set as the current user. + *

+ * + * @param username the unique username for the new account + * @param email the email address associated with the new account + * @param password the password for the new account + * @return {@code true} if registration was successful; {@code false} if the + * username is already taken or the database operation failed + */ + public boolean register(String username, String email, String password ){ + User newUser = new User(username, email, password, Role.NORMAL_USER, new Settings(), new Inbox()); + + if(userDataReader.isEmailTaken(email)){ + throw new IllegalArgumentException("Email already taken"); + } + + boolean success = userDataSender.registerUser(newUser); + + if (success){ + // currentUser = newUser; + // Proceed to login first + return true; + } + return false; + } + + /** + * Logs out the currently authenticated user by clearing the current user state. + */ + public void logout (){ + currentUser = null; } - boolean success = userDataSender.registerUser(newUser); - if (success) { - currentUser = newUser; - return true; + /** + * Returns the currently authenticated user. + * + * @return the current {@link User}, or {@code null} if no user is logged in + */ + public User getCurrentUser(){ + return currentUser; + } + + /** + * Checks whether a user is currently logged in. + * + * @return {@code true} if a user is authenticated; {@code false} otherwise + */ + public boolean isLoggedin(){ + return currentUser != null; } - return false; - } - - /** Logs out the currently authenticated user by clearing the current user state. */ - public void logout() { - currentUser = null; - } - - /** - * Returns the currently authenticated user. - * - * @return the current {@link User}, or {@code null} if no user is logged in - */ - public User getCurrentUser() { - return currentUser; - } - - /** - * Checks whether a user is currently logged in. - * - * @return {@code true} if a user is authenticated; {@code false} otherwise - */ - public boolean isLoggedin() { - return currentUser != null; - } + + public Charity isCharityUser(){return isCharityUser;} } diff --git a/helpmehelpapplication/src/main/resources/fxml/aboutPage.fxml b/helpmehelpapplication/src/main/resources/fxml/aboutPage.fxml index 16bb23f..1d6bbe4 100644 --- a/helpmehelpapplication/src/main/resources/fxml/aboutPage.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/aboutPage.fxml @@ -18,6 +18,7 @@ + @@ -32,472 +33,404 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/helpmehelpapplication/src/main/resources/fxml/available_organizations.fxml b/helpmehelpapplication/src/main/resources/fxml/available_organizations.fxml index d61d0fb..51e0525 100644 --- a/helpmehelpapplication/src/main/resources/fxml/available_organizations.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/available_organizations.fxml @@ -25,7 +25,7 @@ style="-fx-background-color: #f4f4f4;" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" - fx:controller="ntnu.systemutvikling.team6.controller.OrganizationOverviewController"> + fx:controller="ntnu.systemutvikling.team6.controller.AvailableOrganizationController"> @@ -66,873 +66,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -944,95 +79,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + \ No newline at end of file diff --git a/helpmehelpapplication/src/main/resources/fxml/charityPage.fxml b/helpmehelpapplication/src/main/resources/fxml/charityPage.fxml index d24b091..d0a8097 100644 --- a/helpmehelpapplication/src/main/resources/fxml/charityPage.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/charityPage.fxml @@ -1,18 +1,15 @@ - - - @@ -25,508 +22,326 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - + + + + + + + + diff --git a/helpmehelpapplication/src/main/resources/fxml/components/categoryTag.fxml b/helpmehelpapplication/src/main/resources/fxml/components/categoryTag.fxml new file mode 100644 index 0000000..3e50953 --- /dev/null +++ b/helpmehelpapplication/src/main/resources/fxml/components/categoryTag.fxml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/helpmehelpapplication/src/main/resources/fxml/components/inboxCard.fxml b/helpmehelpapplication/src/main/resources/fxml/components/inboxCard.fxml new file mode 100644 index 0000000..112ef98 --- /dev/null +++ b/helpmehelpapplication/src/main/resources/fxml/components/inboxCard.fxml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/helpmehelpapplication/src/main/resources/fxml/components/interestCard.fxml b/helpmehelpapplication/src/main/resources/fxml/components/interestCard.fxml new file mode 100644 index 0000000..5ffb496 --- /dev/null +++ b/helpmehelpapplication/src/main/resources/fxml/components/interestCard.fxml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/helpmehelpapplication/src/main/resources/fxml/components/navbar.fxml b/helpmehelpapplication/src/main/resources/fxml/components/navbar.fxml index f3cca80..30cb898 100644 --- a/helpmehelpapplication/src/main/resources/fxml/components/navbar.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/components/navbar.fxml @@ -1,89 +1,91 @@ + + - - - - - - - - - - - - - + + + + + + + + - - - + + + + + - + + + - - - - - - - + + + + + + + + + + + + + + - + - - + - - - - \ No newline at end of file + diff --git a/helpmehelpapplication/src/main/resources/fxml/components/organizationCard.fxml b/helpmehelpapplication/src/main/resources/fxml/components/organizationCard.fxml index 790c679..9076186 100644 --- a/helpmehelpapplication/src/main/resources/fxml/components/organizationCard.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/components/organizationCard.fxml @@ -16,15 +16,15 @@ - - @@ -238,11 +111,7 @@ - + @@ -253,23 +122,13 @@ - + - - - - - + + @@ -157,6 +100,11 @@ + @@ -167,83 +115,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/helpmehelpapplication/src/main/resources/fxml/frontPage.fxml b/helpmehelpapplication/src/main/resources/fxml/frontPage.fxml index 74c0577..1e095ea 100644 --- a/helpmehelpapplication/src/main/resources/fxml/frontPage.fxml +++ b/helpmehelpapplication/src/main/resources/fxml/frontPage.fxml @@ -21,346 +21,157 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - + + + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + +