Started implumenting a GUI for the program.

This commit is contained in:
2025-03-20 13:07:47 +01:00
parent 5f192d1860
commit d8e0c12b9f
11 changed files with 413 additions and 33 deletions

View File

@@ -7,20 +7,46 @@ import org.intellij.lang.annotations.MagicConstant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID; import java.util.UUID;
/**
* Represents an account in the bank for a user.
*/
public class Account { public class Account {
/**
* List of transactions in the account.<br>
* Each transaction contains information about the transaction, such as the amount, description, and the type of transaction.
*/
ArrayList<Transaction> transactions; ArrayList<Transaction> transactions;
/**
* Name of the account.
*/
String name; String name;
/**
* Balance of the account.
*/
double balance; double balance;
/**
* ID of the account.<br>
* Also works as the Account number.
*/
UUID id; UUID id;
/**
* Interest rate of the account.
*/
@MagicConstant(valuesFromClass = Interests.class) @MagicConstant(valuesFromClass = Interests.class)
double interestRate; double interestRate;
public Account(String name, double balance, @MagicConstant(valuesFromClass = Interests.class) double interestRate) { /**
* Creates a new account.
* @param name Name of the account.
* @param interestRate Interest rate of the account.
*/
public Account(String name, @MagicConstant(valuesFromClass = Interests.class) double interestRate) {
this.name = name; this.name = name;
this.balance = balance; this.balance = 0;
transactions = new ArrayList<>(); transactions = new ArrayList<>();
id = UUID.randomUUID(); id = UUID.randomUUID();
this.interestRate = interestRate; this.interestRate = interestRate;
transactions.add(new Transaction(0, "Account opened", id, id, TransactionType.OPEN));
} }
public void WithdrawTransaction(double amount, String description, UUID destination) { public void WithdrawTransaction(double amount, String description, UUID destination) {
@@ -62,7 +88,7 @@ public class Account {
throw new IllegalArgumentException("Insufficient balance"); throw new IllegalArgumentException("Insufficient balance");
} }
balance -= transaction.getAmount(); balance -= transaction.getAmount();
} else if(transaction.getType() == TransactionType.DEPOSIT) { } else if(transaction.getType() == TransactionType.DEPOSIT || transaction.getType() == TransactionType.OPEN || transaction.getType() == TransactionType.CLOSE) {
if(transaction.getAmount() < 0) { if(transaction.getAmount() < 0) {
throw new IllegalArgumentException("Amount cannot be negative"); throw new IllegalArgumentException("Amount cannot be negative");
} }
@@ -92,7 +118,12 @@ public class Account {
public double getInterest() { public double getInterest() {
return balance * (1+interestRate); return balance * (1+interestRate);
} }
@Override
public String toString() {
return name + " - " + balance + " kr";
}
public static class Interests public static class Interests
{ {
public static final double BANK_ACCOUNT_INTEREST_RATE = 0.001; public static final double BANK_ACCOUNT_INTEREST_RATE = 0.001;

View File

@@ -6,7 +6,7 @@ import static me.zacharias.bank.Account.Interests.BANK_ACCOUNT_INTEREST_RATE;
* This class only works as a way to have prefilled information, but can be replaced by just calling the {@link Account#Account(String, double, double)} instead * This class only works as a way to have prefilled information, but can be replaced by just calling the {@link Account#Account(String, double, double)} instead
*/ */
public class BankAccount extends Account { public class BankAccount extends Account {
public BankAccount(String name, double balance) { public BankAccount(String name) {
super(name, balance, BANK_ACCOUNT_INTEREST_RATE); super(name, BANK_ACCOUNT_INTEREST_RATE);
} }
} }

View File

@@ -12,25 +12,16 @@ import static me.zacharias.bank.Utils.*;
public class Main { public class Main {
User user; User user;
static Gson gson;
static {
GsonBuilder gsonBuilder = new GsonBuilder();
//gsonBuilder.registerTypeAdapter(Account.class, new AccountAdapter());
gson = gsonBuilder.create();
}
public static void main(String[] args) { public static void main(String[] args) {
String user = SHA256("zacharias"); String user = SHA256("user");
File userFile = new File("./users/" + user + ".json"); File userFile = new File("./users/" + user + ".json");
if(!userFile.exists()) { if(!userFile.exists()) {
User u = new User("zacharias"); User u = new User("user");
u.createAccount("Konto", 0.0); u.createAccount("Konto");
Account a = u.getAccount("Konto"); Account a = u.getAccount("Konto");
a.DepositTransaction(104, "Spawnar pängar", UUID.randomUUID()); a.DepositTransaction(104, "Deposit", UUID.randomUUID());
String json = gson.toJson(u); String json = gson.toJson(u);
try { try {
@@ -52,7 +43,7 @@ public class Main {
//return; //return;
} }
String name = "zacharias";//console.readLine("Enter your name: "); String name = "user";//console.readLine("Enter your name: ");
String userHash = SHA256(name); String userHash = SHA256(name);

View File

@@ -7,7 +7,7 @@ import static me.zacharias.bank.Account.Interests.SAVINGS_ACCOUNT_INTEREST_RATE;
*/ */
public class SavingsAccount extends Account{ public class SavingsAccount extends Account{
public SavingsAccount(String name, double balance) { public SavingsAccount(String name) {
super(name, balance, SAVINGS_ACCOUNT_INTEREST_RATE); super(name, SAVINGS_ACCOUNT_INTEREST_RATE);
} }
} }

View File

@@ -1,5 +1,9 @@
package me.zacharias.bank; package me.zacharias.bank;
import me.zacharias.bank.transaction.Transaction;
import me.zacharias.bank.transaction.TransactionType;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID; import java.util.UUID;
@@ -14,14 +18,16 @@ public class User {
accounts = new ArrayList<>(); accounts = new ArrayList<>();
} }
public void createAccount(String name, double balance) { public UUID createAccount(String name) {
Account account = new BankAccount(name, balance); Account account = new BankAccount(name);
accounts.add(account); accounts.add(account);
return account.getId();
} }
public void createSavingsAccount(String name, double balance) { public UUID createSavingsAccount(String name) {
Account account = new SavingsAccount(name, balance); Account account = new SavingsAccount(name);
accounts.add(account); accounts.add(account);
return account.getId();
} }
public Account getAccount(String name) { public Account getAccount(String name) {
@@ -33,7 +39,7 @@ public class User {
return null; return null;
} }
public Account getAccount(UUID id) { public Account getAccount(@NotNull UUID id) {
for (Account account : accounts) { for (Account account : accounts) {
if (account.id.equals(id)) { if (account.id.equals(id)) {
return account; return account;
@@ -42,17 +48,25 @@ public class User {
return null; return null;
} }
public void deleteAccount(Account account) { public void deleteAccount(@NotNull Account account) {
Account base = null; Account base = null;
for(Account a : accounts) { for(Account a : accounts) {
if(a instanceof BankAccount) { if(a.getId().equals(account.getId())) {
base = a; base = a;
} }
} }
if(base == null) { if(base == null) {
throw new IllegalArgumentException("No bank accounts found"); throw new IllegalArgumentException("No other bank accounts found");
} }
base.TransferTransaction(account.getBalance(), "Account closed", account.getId(), base.getId()); base.handleTransaction(new Transaction(account.getBalance(), "Account closed", account.getId(), base.getId(), TransactionType.CLOSE));
accounts.remove(account); accounts.remove(account);
} }
public String getName() {
return name;
}
public ArrayList<Account> getAccounts() {
return accounts;
}
} }

View File

@@ -1,5 +1,8 @@
package me.zacharias.bank; package me.zacharias.bank;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
@@ -14,6 +17,22 @@ import java.security.SecureRandom;
import java.util.Base64; import java.util.Base64;
public class Utils { public class Utils {
public static final Gson gson;
static {
GsonBuilder gsonBuilder = new GsonBuilder();
//gsonBuilder.registerTypeAdapter(Account.class, new AccountAdapter());
gson = gsonBuilder.create();
File users = new File("./users");
if(!users.exists()) {
users.mkdir();
}
}
public static String SHA256(String input) { public static String SHA256(String input) {
MessageDigest sha256 = null; MessageDigest sha256 = null;
try { try {

View File

@@ -0,0 +1,67 @@
package me.zacharias.bank.app;
import me.zacharias.bank.Account;
import me.zacharias.bank.transaction.Transaction;
import javax.swing.*;
import java.awt.*;
public class AccountView extends JPanel {
Main bankApplication;
Account account;
JLabel accountName;
JLabel balance;
JLabel AccountNumber;
JList<Transaction> transactionList;
public AccountView(Main bankApplication, Account account) {
this.bankApplication = bankApplication;
this.account = account;
this.setLayout(null);
accountName = new JLabel(account.getName());
accountName.setBounds(10, 10, 200, 30);
balance = new JLabel(account.getBalance() + " kr");
balance.setBounds(10, 50, 200, 30);
AccountNumber = new JLabel(account.getId().toString());
AccountNumber.setBounds(10, 90, 200, 30);
transactionList = new JList<>();
transactionList.setBounds(10, 130, 200, 30);
transactionList.setModel(new DefaultListModel<>());
transactionList.setBackground(Color.GRAY);
transactionList.setCellRenderer(new ListCellRenderer<Transaction>() {
@Override
public Component getListCellRendererComponent(JList<? extends Transaction> list, Transaction value, int index, boolean isSelected, boolean cellHasFocus) {
JButton label = new JButton();
label.setText(value.getDescription() + " " + value.getAmount() + " kr");
label.setBackground(Color.GRAY);
label.addActionListener(e -> {
bankApplication.showAccount(account);
});
return label;
}
});
this.add(accountName);
this.add(balance);
this.add(AccountNumber);
this.add(transactionList);
}
@Override
protected void paintComponent(Graphics g) {
accountName.setBounds(10, 10, 200, 30);
balance.setBounds(10, 50, 200, 30);
AccountNumber.setBounds(10, 90, 200, 30);
transactionList.setBounds(10, 130, 200, 30);
transactionList.setListData(account.getTransactions().toArray(new Transaction[0]));
super.paintComponent(g);
}
}

View File

@@ -0,0 +1,135 @@
package me.zacharias.bank.app;
import me.zacharias.bank.User;
import me.zacharias.bank.Utils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
public class Login extends JPanel {
//String username;
//String password;
User user = null;
JTextField usernameField;
JLabel usernameLabel;
JPasswordField passwordField;
JLabel passwordLabel;
JLabel error;
JButton loginButton;
Main bankApplication;
public Login(Main bankApplication) {
this.bankApplication = bankApplication;
this.setLayout(null);
usernameField = new JTextField();
usernameField.setBounds(getWidth()/2-100, 10, 200, 30);
usernameField.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
usernameField.selectAll();
}
@Override
public void focusLost(FocusEvent e) {
usernameField.select(0, 0);
}
});
usernameLabel = new JLabel("Username");
usernameLabel.setBounds(getWidth()/2-100-80, 10, 80, 30);
passwordField = new JPasswordField();
passwordField.setBounds(getWidth()/2-100, 50, 200, 30);
passwordField.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
usernameField.selectAll();
}
@Override
public void focusLost(FocusEvent e) {
usernameField.select(0, 0);
}
});
passwordLabel = new JLabel("Password");
passwordLabel.setBounds(getWidth()/2-100-80, 50, 80, 30);
error = new JLabel();
error.setBounds(getWidth()/2-100, 80, 200, 10);
error.setFont(new Font("Arial", Font.BOLD, 10));
error.setForeground(Color.RED);
loginButton = new JButton("Login");
loginButton.setBounds(getWidth()/2-100, 95, 200, 30);
loginButton.addActionListener(e -> {
String username = usernameField.getText();
String userHash = Utils.SHA256(username);
String password = new String(passwordField.getPassword());
File userFile = new File("users/" + userHash + ".json");
if (!userFile.exists()) {
//JOptionPane.showMessageDialog(null, "Wrong username or password");
error.setText("Wrong username or password");
return;
}
String userData;
try {
userData = Utils.Decrypt(Utils.ReadFile(userFile), password);
} catch (Exception ex) {
//JOptionPane.showMessageDialog(null, "Wrong username or password");
error.setText("Wrong username or password");
return;
}
try{
user = Utils.gson.fromJson(userData, User.class);
}catch (Exception ex){
//JOptionPane.showMessageDialog(null, "Wrong username or password");
error.setText("Wrong username or password");
return;
}
error.setText("");
bankApplication.login(user);
});
this.add(usernameField);
this.add(usernameLabel);
this.add(passwordField);
this.add(passwordLabel);
this.add(error);
this.add(loginButton);
}
public User getUser() {
return user;
}
@Override
protected void paintComponent(Graphics g) {
usernameField.setBounds(getWidth()/2-100, 10, 200, 30);
usernameLabel.setBounds(getWidth()/2-100-80, 10, 80, 30);
passwordField.setBounds(getWidth()/2-100, 50, 200, 30);
passwordLabel.setBounds(getWidth()/2-100-80, 50, 80, 30);
error.setBounds(getWidth()/2-100, 80, 200, 10);
loginButton.setBounds(getWidth()/2-100, 95, 200, 30);
super.paintComponent(g);
}
public void clear() {
usernameField.setText("");
passwordField.setText("");
error.setText("");
}
}

View File

@@ -0,0 +1,57 @@
package me.zacharias.bank.app;
import me.zacharias.bank.Account;
import me.zacharias.bank.User;
import javax.swing.*;
import java.awt.*;
public class Main extends JPanel {
public static void main(String[] args) {
new Main();
}
JFrame frame;
Login login;
MainMenu mainManu;
AccountView accountView;
Timer timer = new Timer(100, e -> {frame.repaint();});
public Main() {
frame = new JFrame("Bank");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
login = new Login(this);
login.setBounds(0, 0, 800, 600);
frame.add(login);
frame.setVisible(true);
timer.start();
}
public void login(User user) {
frame.remove(login);
mainManu = new MainMenu(user, this);
frame.add(mainManu);
frame.setVisible(true);
}
public void logout() {
frame.remove(mainManu);
login.clear();
frame.add(login);
frame.setVisible(true);
}
public void showAccount(Account account) {
frame.remove(mainManu);
accountView = new AccountView(this, account);
frame.add(accountView);
frame.setVisible(true);
}
}

View File

@@ -0,0 +1,66 @@
package me.zacharias.bank.app;
import me.zacharias.bank.Account;
import me.zacharias.bank.User;
import javax.swing.*;
import java.awt.*;
public class MainMenu extends JPanel {
User user;
Main bankApplication;
JLabel welcome;
JButton logout;
JList<Account> accountList;
public MainMenu(User user, Main bankApplication) {
this.user = user;
this.bankApplication = bankApplication;
this.setLayout(null);
welcome = new JLabel("Welcome " + user.getName());
welcome.setBounds(getWidth()/2-100, 10, 200, 30);
logout = new JButton("Logout");
logout.setBounds(getWidth()/2-100, getHeight()-50, 200, 30);
logout.addActionListener(e -> {
bankApplication.logout();
});
accountList = new JList<>();
accountList.setBounds(getWidth()/2-100, 80, 200, 30);
accountList.setModel(new DefaultListModel<>());
accountList.setBackground(Color.GRAY);
accountList.setCellRenderer(new ListCellRenderer<Account>() {
@Override
public Component getListCellRendererComponent(JList<? extends Account> list, Account value, int index, boolean isSelected, boolean cellHasFocus) {
JButton label = new JButton();
label.setText(value.getName() + " " + value.getBalance() + " kr");
label.setBackground(Color.GRAY);
label.addActionListener(e -> {
bankApplication.showAccount(value);
});
return label;
}
});
this.add(welcome);
this.add(logout);
this.add(accountList);
}
@Override
protected void paintComponent(Graphics g) {
welcome.setBounds(getWidth()/2-100, 10, 200, 30);
logout.setBounds(getWidth()/2-100, getHeight()-50, 200, 30);
accountList.setBounds(getWidth()/2-100, 80, 200, 30);
accountList.setListData(user.getAccounts().toArray(new Account[0]));
super.paintComponent(g);
}
}

View File

@@ -1,5 +1,5 @@
package me.zacharias.bank.transaction; package me.zacharias.bank.transaction;
public enum TransactionType { public enum TransactionType {
WITHDRAW, DEPOSIT, TRANSFER WITHDRAW, DEPOSIT, OPEN, TRANSFER, CLOSE
} }