Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
e2760fb
Unit tests for Donation, User, and Organization classes
haavajor Mar 5, 2026
16b15ab
Fixed main class configuration
Mar 13, 2026
2f72518
Removed unnecessary file
Mar 13, 2026
6b34569
Removed unnecessary file
Mar 13, 2026
3edb587
Class to move between scenes
Mar 13, 2026
9ff4e73
Changed name to big capital letter
Mar 13, 2026
fe5cf4d
css style for buttons
Mar 13, 2026
0b68fc4
Created homepage and sign in page for application
Mar 13, 2026
1e6fe5d
Controller for homepage
Mar 13, 2026
d985616
Controller for sign in page
Mar 13, 2026
e68902a
Changed name for userLogin to userSignIn
Mar 13, 2026
e58c20b
Updated main to show application
Mar 13, 2026
4da4e06
Connected loggin use case to javafx
Mar 13, 2026
d81a1a6
Made switch method with path and also controller as parameter
Mar 14, 2026
74e1a08
Added email validation
Mar 14, 2026
c53f3bb
Added email validation
Mar 14, 2026
22c7cf8
Made register page
Mar 14, 2026
40ce85f
Slutt å spore givehope.db
Mar 19, 2026
fb8b4af
Merge GUI - fjern givehope.db
Mar 19, 2026
79773d1
refactor: update organization table columns to match Innsamlingskontr…
Mar 19, 2026
a65b2ca
refactor: set initalize method to public
Mar 19, 2026
97beba5
refactor: Changed class to match Innsamlingskontrollen API
Mar 19, 2026
afe74c1
feat: add OrganizationDAO for saving and retrieving organizations
Mar 19, 2026
bfad5ab
feat: connect explore organization button to OrganizationsView
Mar 19, 2026
84c54da
feat: connect explore organization button to OrganizationsView
Mar 19, 2026
cd6a72f
feat: created controller for OrganizationsView
Mar 19, 2026
86087d7
feat: add organization view with search and pagination
Mar 19, 2026
a983a95
Merge branch 'DEV' into donation
lukasce Mar 19, 2026
eed6746
style: apply consistent design system across all pages
Mar 19, 2026
dfd90cb
feat: add SessionManager to track signed-in user state
Mar 19, 2026
b163b27
style: add OrganizationView stylesheet and update organizations layout
Mar 19, 2026
d45b04f
style: add OrganizationView stylesheet for organization cards and sea…
Mar 19, 2026
2a45c0a
refactor: delete style.css
Mar 19, 2026
61d4cab
chore: update Home.fxml to use Global.css stylesheet
Mar 19, 2026
12d14e9
feat: add session-aware navigation and responsive card layout in Orga…
Mar 19, 2026
b8cac2a
feat: store signed-in user in SessionManager after successful sign-in
Mar 19, 2026
ccec682
Merge pull request #20 from Gruppe-26-IDATT1005/donation
lukasce Mar 20, 2026
f1b8d2f
refactor: moved scrollbar style from OrganizationView to Global
Mar 24, 2026
ff8a60a
refactor: moved scrollbar style from OrganizationView to Global
Mar 24, 2026
5fb186f
style: add profile-label styles
Mar 24, 2026
6ea7bf1
feat: add MyProfile view with profile info, statistics, donation hist…
Mar 24, 2026
84cf18f
feat: add MyProfileController
Mar 24, 2026
b80dbbf
feat: add NavbarController with navigation and Navbar FXML layout
Mar 24, 2026
939e58e
feat: update SignIn view to use shared Navbar and add button styles
Mar 24, 2026
618b21b
feat: update Register view to use shared Navbar and add button styles
Mar 24, 2026
ac9ef75
feat: navigate to MyProfile when user is signed in
Mar 24, 2026
f17cb5b
chore: initialize database and seed organizations on app startup
Mar 24, 2026
61e9c12
Merge pull request #21 from Gruppe-26-IDATT1005/feature/userStatistics
mariukle Mar 24, 2026
81acede
Merge branch 'DEV' into feature/MyProfile
mariukle Mar 24, 2026
5f80dfd
Merge pull request #23 from Gruppe-26-IDATT1005/feature/MyProfile
mariukle Mar 24, 2026
5713a1a
feat: add shared Navbar with MainView and MainController for unified …
Apr 9, 2026
6bb4cb8
refactor: add NavigationAware interface to simplify page navigation i…
Apr 9, 2026
42cd924
style: update navbar and organization view styles
Apr 9, 2026
57cea20
feat: update OrganizationController to use new navigation setup
Apr 9, 2026
33671d9
refactor: move FXML resources from fxml/ to view/ directory
Apr 9, 2026
b7ba8bf
moved
Apr 9, 2026
0840806
Merge branch 'DEV' into feature/refactor-navbar
mariukle Apr 9, 2026
02527cb
Merge pull request #26 from Gruppe-26-IDATT1005/feature/refactor-navbar
mariukle Apr 9, 2026
56d7d5e
feat: redesign Home view with hero section, stats stripe, and featur…
Apr 9, 2026
e739553
fix: remove test code from Main, restore setId on User, and fix Donat…
Apr 9, 2026
3a2a168
chore: remove unused SceneManager imports from controllers
Apr 9, 2026
430cfb0
feature: connect explore organizations button
Apr 9, 2026
a142fef
Merge pull request #28 from Gruppe-26-IDATT1005/refactor/home-page-la…
mariukle Apr 9, 2026
c46854f
bug: fixed sizing and scrolling on my profile page
Apr 9, 2026
b07619b
feature: sign-in button changes to my-profile button when logged in
Apr 9, 2026
8d097ec
feature: Added logout feature
Apr 9, 2026
23325b5
Merge pull request #30 from Gruppe-26-IDATT1005/feature/navbar-auth-s…
mariukle Apr 9, 2026
7de73d0
Added javadoc to DonationDao and UserStatistics
Apr 7, 2026
7ae6ae5
Mde changes to FavoriteOrganization, so that the statistcs page shows…
Apr 10, 2026
3a6839b
Added addTestData function to add test date for testing implemented f…
Apr 10, 2026
8d6adb9
Made changes to labeling, design and size of parts of MyProfile page
Apr 10, 2026
371ff89
Added functions and methodsm that connects Backend methods for user s…
Apr 10, 2026
0c88339
changed name of method, to match what methods actually returns (one o…
Apr 10, 2026
9c96c8f
Merge pull request #35 from Gruppe-26-IDATT1005/feature/userStatistic…
lukasce Apr 10, 2026
69dc43b
feat: add multi-step donation flow with session state
Apr 10, 2026
5a18400
feat: wire donation flow into main navigation and organization view
Apr 10, 2026
fef6b86
refactor: rename and remove inconsistent method and enum names for cl…
Apr 10, 2026
60fd71f
Generated javadoc for Dao-classes
Apr 14, 2026
537b48d
Remove unused handleGoHome() and handleSignIn() methods
Apr 14, 2026
572c111
Add press/scale animation to back button and remove stray blank lines…
Apr 14, 2026
a10b956
Update to renamed SessionManager.getSignedInUser() and user.getEmail()
Apr 14, 2026
c266a51
- Initialize database on startup in Main.start()
Apr 14, 2026
43ea467
Added spacing between the labels
Apr 14, 2026
ebe715f
Refactor: removed the info page and added an not loggen in page inste…
Apr 14, 2026
59d1121
Refactor: simplify DonationNotLoggedIn controller and remove unused f…
Apr 14, 2026
32108d2
Added guard for negative amount
Apr 14, 2026
dc50cd2
feat: finish not logged in page for donation flow
Apr 14, 2026
9ff603d
refactor: redirect to amount or not logged in page based on auth state
Apr 14, 2026
b67a5f2
Refactor: Moved common styling to Global.css
Apr 14, 2026
f3aa1ef
refactor: improve Sign In and Register page layout and styling
Apr 14, 2026
c1fc3b8
Merge pull request #39 from Gruppe-26-IDATT1005/refactor/signin-regis…
lukasce Apr 15, 2026
82351ee
Merge pull request #37 from Gruppe-26-IDATT1005/feature/donation-flow
lukasce Apr 15, 2026
621da6c
Unit tests
haavajor Apr 15, 2026
eee547d
Merge branch 'main' into UnitTests
haavajor Apr 15, 2026
d009756
Added javadoc to multiple classes
Apr 15, 2026
a406ff6
Added javadoc to UserRegister and UserSignIn
Apr 15, 2026
349171c
Added javadoc to Page enum and NavigationAware
Apr 15, 2026
fe579b9
feat: add Jsoup dependency for web scraping organization details
Apr 15, 2026
2acf915
feat: add organization detail popup with logo, description and action…
Apr 15, 2026
93d9ab7
feat: add fetchDetails method to scrape description and logo from Inn…
Apr 15, 2026
bacf2ec
refactor: move shared button styles to Global.css and clean up unused…
Apr 15, 2026
6f8eb57
chore: minor changes
Apr 15, 2026
b151990
Merge pull request #43 from Gruppe-26-IDATT1005/feature/detail-page
mariukle Apr 15, 2026
6c6829b
Merge branch 'DEV' into documentation/javadoc
lukasce Apr 15, 2026
47ecb83
Merge pull request #44 from Gruppe-26-IDATT1005/documentation/javadoc
lukasce Apr 15, 2026
e9ee649
Merge branch 'DEV' into UnitTests
haavajor Apr 16, 2026
64e470c
Deleted not-used CauseDao class
Apr 16, 2026
7ab1429
Merge branch 'DEV' into Backend-UnitTests
haavajor Apr 16, 2026
74f2cc5
Merge pull request #46 from Gruppe-26-IDATT1005/Backend-UnitTests
haavajor Apr 16, 2026
bfa99ed
Merge pull request #45 from Gruppe-26-IDATT1005/UnitTests
haavajor Apr 16, 2026
3708901
Javadoc for UI classes
Apr 16, 2026
e22cc28
Documentation: Added javadoc and removed unused method and files
Apr 16, 2026
c04752c
Documentation: Added javadoc and removed unused method and files
Apr 16, 2026
dcfbc7b
Merge branch 'DEV' into documentation/javadoc
Apr 16, 2026
124278e
Merge with dev
Apr 16, 2026
44eb8fc
Merge pull request #47 from Gruppe-26-IDATT1005/documentation/javadoc
mariukle Apr 16, 2026
e1eb759
fixed package-import bug
Apr 16, 2026
66b0475
Refactor: moved OrganizationDetails to integration, since its job is …
Apr 19, 2026
0355917
fix: fix all tests
Apr 21, 2026
a05b1f2
feat: logo is bigger and takes you to homepage on interaction
Apr 21, 2026
62af020
fix: update text from norwegian to english
Apr 21, 2026
8325390
fix: fixes bug in description in organization detail pop up
Apr 21, 2026
27817bf
refactor: remove unused button
Apr 21, 2026
28062f2
refactor: remove unused methods
Apr 21, 2026
ee1b0cd
fix: removed duplicate plugin
Apr 21, 2026
3365596
Merge pull request #49 from Gruppe-26-IDATT1005/fix/tests-and-bugs
mariukle Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ build/
.DS_Store

### data ###
*.db
givehope.db
/data/
21 changes: 12 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
</properties>

<dependencies>

<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
Expand All @@ -31,7 +29,6 @@
<version>${javafx.version}</version>
</dependency>

<!-- JUnit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand All @@ -42,7 +39,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
<version>2.18.3</version>
</dependency>

<dependency>
Expand All @@ -51,28 +48,34 @@
<version>3.46.1.0</version>
</dependency>

<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>

</dependencies>

<build>
<plugins>

<!-- JavaFX Plugin -->
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>ui.GiveHopeGIU</mainClass>
<mainClass>app.Main</mainClass>
<options>
<option>-Dfile.encoding=UTF-8</option>
<option>-Dstdout.encoding=UTF-8</option>
</options>
</configuration>
</plugin>

<!-- Surefire for JUnit -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
</plugin>

</plugins>
</build>
</project>
4 changes: 0 additions & 4 deletions src/main/java/app/GiveHopeApp.java

This file was deleted.

116 changes: 70 additions & 46 deletions src/main/java/app/Main.java
Original file line number Diff line number Diff line change
@@ -1,63 +1,87 @@
package app;

import domain.organization.Organization;
import integration.OrganizationDetails;
import integration.InnsamlingskontrollenClient;
import application.security.PasswordHasher;
import application.user.UserRegister;
import domain.donation.Donation;
import domain.organization.Organization;
import domain.user.User;
import integration.InnsamlingskontrollenClient;
import integration.security.Sha256PasswordHasher;
import java.math.BigDecimal;
import java.util.List;
import persistence.DonationDao;
import persistence.OrganizationDao;
import persistence.UserDao;
import persistence.UserRepository;
import java.sql.SQLException;

import persistence.dao.DonationDao;
import persistence.dao.OrganizationDao;
import persistence.dao.UserDao;
import persistence.db.Database;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main {
public class Main extends Application{
public static void main(String[] args) {
try {
Database.getConnection();
System.out.println("Database connected");

UserDao userDao = new UserDao();
OrganizationDao orgDao = new OrganizationDao();
DonationDao donationDao = new DonationDao();

PasswordHasher hasher = new Sha256PasswordHasher();
UserRepository userRepo = new UserDao();
UserRegister userReg = new UserRegister(hasher, userRepo);

// Test brukerregistrering
userReg.execute("testuser", "12345678", "passord123", "test@example.com");
System.out.println("Inserted user!");

User user = userDao.findByEmail("test@example.com").orElseThrow();
System.out.println("Hentet bruker: " + user.getUsername() + ", id=" + user.getID());

// Hent og lagre organisasjoner fra Innsamlingskontrollen
System.out.println("Henter organisasjoner fra Innsamlingskontrollen...");
Organization[] fetchedOrgs = InnsamlingskontrollenClient.fetchOrganizations();
for (Organization org : fetchedOrgs) {
orgDao.insert(org);
launch(args);
}

@Override
public void start(Stage stage) throws Exception {
Database.initializeDatabase();
System.out.println("DB path: " + new java.io.File("givehope.db").getAbsolutePath());
OrganizationDetails details = InnsamlingskontrollenClient.fetchDetails(
"https://www.innsamlingskontrollen.no/organisasjoner/caritas-norge/"
);
System.out.println("Description: " + details.getDescription());
System.out.println("Logo: " + details.getLogoUrl());
OrganizationDao orgDao = new OrganizationDao();
Organization[] orgs = InnsamlingskontrollenClient.fetchOrganizations();
for (Organization org : orgs) {
orgDao.insert(org);
}
System.out.println("Lastet inn " + fetchedOrgs.length + " organisasjoner");

List<Organization> orgs = orgDao.getAll();
System.out.println("Organisasjoner i DB: " + orgs.size());
System.out.println("Første org: " + orgs.get(0).getName() + ", org_number=" + orgs.get(0).getOrgNumber());
addTestdata();

// Test donasjon med første org fra DB
Donation donation = new Donation(new BigDecimal("100.00"), user, orgs.get(0));
donationDao.insert(donation);
System.out.println("Inserted donation, id=" + donation.getId());
Parent root = FXMLLoader.load(getClass().getResource("/view/MainView.fxml"));
Scene scene = new Scene(root, 1275, 725);

stage.setTitle("GiveHope");
stage.setScene(scene);
stage.show();
}

List<Donation> donations = donationDao.findByUser(user.getID());
System.out.println("Antall donasjoner for bruker: " + donations.size());
private void addTestdata() throws SQLException {
UserDao userDao = new UserDao();
DonationDao donationDao = new DonationDao();
OrganizationDao orgDao = new OrganizationDao();

} catch (Exception e) {
e.printStackTrace();
if (userDao.existsByEmail("test@test.no")) return;

PasswordHasher hasher = new Sha256PasswordHasher();
String hashedPassword = hasher.hash("test");
User user = new User("test", "12345678", hashedPassword, "test@test.no");
userDao.insert(user);

Organization org = orgDao.getAll().get(0);

donationDao.insert(new Donation(new BigDecimal(100), user, org));
donationDao.insert(new Donation(new BigDecimal(250), user, org));
donationDao.insert(new Donation(new BigDecimal(500), user, org));
donationDao.insert(new Donation(new BigDecimal(300), user, org));
donationDao.insert(new Donation(new BigDecimal(1000), user, org));
donationDao.insert(new Donation(new BigDecimal(700), user, org));
donationDao.insert(new Donation(new BigDecimal(250), user, org));

if (!userDao.existsByEmail("test2@test.no")) {
String hashedPassword2 = hasher.hash("test2");
User user2 = new User("test2", "87654321", hashedPassword2, "test2@test.no");
userDao.insert(user2);

Organization org2 = orgDao.getAll().get(1);

donationDao.insert(new Donation(new BigDecimal(150), user2, org2));
donationDao.insert(new Donation(new BigDecimal(400), user2, org2));
donationDao.insert(new Donation(new BigDecimal(600), user2, org2));
}
}
}
}
4 changes: 4 additions & 0 deletions src/main/java/application/security/PasswordHasher.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package application.security;

/**
* Interface that creates a "contract" for which methods the class that implements it, needs.
* Interface is created for SHA256PasswordHasher.
*/
public interface PasswordHasher {

String hash(String password);
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/application/user/UserDonate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package application.user;

import domain.donation.Donation;
import domain.organization.Organization;
import domain.user.User;
import persistence.dao.DonationDao;
import java.math.BigDecimal;

/**
* Use case for handling donations made by a user to an organization.
* Creates a {@link Donation} and persists it to the database.
*/
public class UserDonate {
private final DonationDao donationDao;

/**
* Creates a new {@code UserDonate} with a default {@link DonationDao}.
*/
public UserDonate() {
this.donationDao = new DonationDao();
}

/**
* Executes the donation use case by creating and saving a donation.
* @param user the user making the donation
* @param org the organization receiving the donation
* @param amount the donation amount in NOK
*/
public void execute(User user, Organization org, BigDecimal amount) {
Donation donation = new Donation(amount, user, org);
donationDao.insert(donation);
}
}
4 changes: 2 additions & 2 deletions src/main/java/application/user/UserLogin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import application.security.PasswordHasher;
import domain.user.User;
import persistence.UserRepository;
import persistence.dao.UserRepository;

public class UserLogin {

Expand All @@ -16,7 +16,7 @@ public UserLogin(PasswordHasher hasher, UserRepository repo) {

public User execute(String login, String password) {
// normalize (trim etc.)
login.trim().toLowerCase();
login = login.trim().toLowerCase();

User user = repo.findByLogin(login)
.orElseThrow(() -> new IllegalArgumentException("Invalid credentials"));
Expand Down
35 changes: 27 additions & 8 deletions src/main/java/application/user/UserRegister.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,57 @@

import application.security.PasswordHasher;
import domain.user.User;
import persistence.UserRepository;

import persistence.dao.UserRepository;

/**
* The UserRegister class is responsible for handling the user registration process.
* It ensures that the provided user details meet the necessary criteria and that
* the username and email are not already in use. It also hashes the user's password
* before saving the user information into the repository.
*/
public class UserRegister {

private final PasswordHasher hasher;
private final UserRepository repo;

public UserRegister(PasswordHasher hasher, UserRepository repo) {
/**
* Constructs a {@code UserRegister} instance responsible for handling the user registration process.
* It ensures user details meet validation criteria, such as uniqueness of username and email,
* and hashes passwords before saving user information into the repository.
*
* @param hasher a {@code PasswordHasher} implementation used to hash user passwords.
* @param repo a {@code UserRepository} implementation responsible for storing user data.
*/
public UserRegister(PasswordHasher hasher, UserRepository repo) {
this.hasher = hasher;
this.repo = repo;
}

/**
* Executes a user registration.
* Validation checks, checks if username or e-mail already exists.
* Hashes inputted password using PasswordHasher, that uses SHA256PasswordHasher.
* Creates user object, and inserts it into UserRepository using insert method.
* @param username
* @param phoneNumber
* @param password
* @param email
*/
public void execute(String username, String phoneNumber, String password, String email) {
username = username.trim();
email = email.trim().toLowerCase();
phoneNumber = phoneNumber.trim();

// duplicate check (repo.existsByEmail)
if (repo.existsByEmail(email)) {
throw new IllegalArgumentException("Email already in use");
}
if (repo.existsByUsername(username)) {
throw new IllegalArgumentException("This username is taken");
}

// hash password (optional)
String hashedPassword = hasher.hash(password);

// new User(...) (domain validates)
User user = new User(username, phoneNumber, hashedPassword, email);

// saves user
repo.insert(user);
}
}
52 changes: 52 additions & 0 deletions src/main/java/application/user/UserSignIn.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package application.user;

import application.security.PasswordHasher;
import domain.user.User;
import persistence.dao.UserRepository;

/**
* The UserSignIn class handles the process of user authentication.
* It verifies the input credentials (login and password) against the stored user data.
* The password is validated through hashing and comparison with the stored hash.
*/
public class UserSignIn {

private final PasswordHasher hasher;
private final UserRepository repo;

/**
* Constructs a {@code UserSignIn} instance responsible for user authentication.
* It handles the process of verifying user credentials by comparing the provided
* input with stored data in the repository and validating the password through hashing.
*
* @param hasher a {@code PasswordHasher} implementation used to hash and validate user passwords.
* @param repo a {@code UserRepository} implementation that stores user authentication data.
*/
public UserSignIn(PasswordHasher hasher, UserRepository repo) {
this.hasher = hasher;
this.repo = repo;
}

/**
* Execute methods, that takes in inputted login and password.
* Checks via UserRepository if login exists in database.
* Compares hashed input password with hashed password in database.
* @param login inputted login by user
* @param password inputted password by user
* @return user object, if it exists.
*/
public User execute(String login, String password) {
login.trim().toLowerCase();

User user = repo.findByLogin(login)
.orElseThrow(() -> new IllegalArgumentException("Invalid credentials"));

String hashedInput = hasher.hash(password);

if (!hashedInput.equals(user.getPassword())) {
throw new IllegalArgumentException("Invalid password");
}

return user;
}
}
Loading
Loading