Untitled

 avatar
unknown
plain_text
20 days ago
13 kB
0
Indexable
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.List;

public class ExpenseTracker {
    private JFrame frame;
    private JTabbedPane tabbedPane;
    private JTable spendingTable, transactionTable;
    private DefaultTableModel spendingModel, transactionModel;
    private JLabel totalExpenseLabel, balanceLabel, savingsLabel;
    private HashMap<String, HashMap<String, Double>> monthlySpendingData;
    private List<Object[]> transactionHistory;
    private double income = 0.0;
    private String currentUser = null;
    private String selectedMonth = "January"; // Default selected month

    private static final String DATA_FILE_PREFIX = "expense_data_"; // Prefix for saving per-user data file

    public ExpenseTracker() {
        monthlySpendingData = new HashMap<>();
        transactionHistory = new ArrayList<>();
        showLoginDialog();
    }

    private void showLoginDialog() {
        JPanel loginPanel = new JPanel();
        loginPanel.setLayout(new BoxLayout(loginPanel, BoxLayout.Y_AXIS));

        JTextField usernameField = new JTextField(15);
        JPasswordField passwordField = new JPasswordField(15);
        JButton loginButton = new JButton("Login");
        JButton registerButton = new JButton("Register");

        loginPanel.add(new JLabel("Username:"));
        loginPanel.add(usernameField);
        loginPanel.add(new JLabel("Password:"));
        loginPanel.add(passwordField);
        loginPanel.add(loginButton);
        loginPanel.add(registerButton);

        loginButton.addActionListener(e -> {
            String username = usernameField.getText().trim();
            String password = new String(passwordField.getPassword()).trim();
            if (username.isEmpty() || password.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "Please enter both username and password.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            if (login(username, password)) {
                currentUser = username;
                loadData();
                initialize();
                JOptionPane.showMessageDialog(frame, "Login successful!");
                frame.setVisible(true);
            } else {
                JOptionPane.showMessageDialog(frame, "Invalid credentials", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        registerButton.addActionListener(e -> {
            String username = usernameField.getText().trim();
            String password = new String(passwordField.getPassword()).trim();
            if (username.isEmpty() || password.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "Please enter both username and password.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            if (register(username, password)) {
                JOptionPane.showMessageDialog(frame, "Registration successful!");
            } else {
                JOptionPane.showMessageDialog(frame, "Username already taken", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        frame = new JFrame("Login");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.add(loginPanel);
        frame.setLocationRelativeTo(null); // Center the frame on the screen
        frame.setVisible(true);
    }

    private boolean login(String username, String password) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_data.dat"))) {
            HashMap<String, String> userData = (HashMap<String, String>) ois.readObject();
            return userData.containsKey(username) && userData.get(username).equals(password);
        } catch (IOException | ClassNotFoundException e) {
            return false; // Error in loading data, assuming user doesn't exist
        }
    }

    private boolean register(String username, String password) {
        HashMap<String, String> userData;
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_data.dat"))) {
            userData = (HashMap<String, String>) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            userData = new HashMap<>();
        }

        if (userData.containsKey(username)) {
            return false;
        }

        userData.put(username, password);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user_data.dat"))) {
            oos.writeObject(userData);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    private void initialize() {
        frame = new JFrame("Expense Tracker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);

        tabbedPane = new JTabbedPane();

        // Spending Tab
        JPanel spendingPanel = new JPanel(new BorderLayout());
        spendingModel = new DefaultTableModel(new String[]{"Category", "Amount"}, 0);
        spendingTable = new JTable(spendingModel);
        updateSpendingTable();
        spendingPanel.add(new JScrollPane(spendingTable), BorderLayout.CENTER);

        JPanel summaryPanel = new JPanel(new GridLayout(5, 1));
        totalExpenseLabel = new JLabel();
        balanceLabel = new JLabel();
        savingsLabel = new JLabel();

        JComboBox<String> monthSelector = new JComboBox<>(getMonths());
        monthSelector.setSelectedItem(selectedMonth);
        monthSelector.addActionListener(e -> {
            selectedMonth = (String) monthSelector.getSelectedItem();
            updateSpendingTable();
            updateGraph((JPanel) tabbedPane.getComponentAt(1)); // Refresh graph
            updateTransactionTable();
        });

        summaryPanel.add(new JLabel("Select Month:"));
        summaryPanel.add(monthSelector);
        summaryPanel.add(totalExpenseLabel);
        summaryPanel.add(balanceLabel);
        summaryPanel.add(savingsLabel);

        spendingPanel.add(summaryPanel, BorderLayout.NORTH);

        JPanel spendingButtons = new JPanel();
        JButton addIncomeButton = new JButton("+ Income");
        addIncomeButton.addActionListener(e -> addIncome());
        JButton addExpenseButton = new JButton("+ Expense");
        addExpenseButton.addActionListener(e -> addExpense());
        spendingButtons.add(addIncomeButton);
        spendingButtons.add(addExpenseButton);
        spendingPanel.add(spendingButtons, BorderLayout.SOUTH);

        tabbedPane.add("Spending", spendingPanel);

        // Graph Tab
        JPanel graphPanel = new JPanel(new BorderLayout());
        updateAnnualGraph(graphPanel); // Initial graph update
        tabbedPane.add("Graph", graphPanel);

        // Transactions Tab
        JPanel transactionPanel = new JPanel(new BorderLayout());
        transactionModel = new DefaultTableModel(new String[]{"Date", "Category", "Amount"}, 0);
        transactionTable = new JTable(transactionModel);
        updateTransactionTable();
        transactionPanel.add(new JScrollPane(transactionTable), BorderLayout.CENTER);
        tabbedPane.add("Transactions", transactionPanel);

        frame.add(tabbedPane);
        frame.setVisible(true);
    }

    private void addIncome() {
        String incomeStr = JOptionPane.showInputDialog(frame, "Enter income amount:");
        try {
            double amount = Double.parseDouble(incomeStr);
            income += amount;
            updateSummaryLabels();
            saveData();
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(frame, "Invalid amount.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void addExpense() {
        String category = JOptionPane.showInputDialog(frame, "Enter category:");
        String amountStr = JOptionPane.showInputDialog(frame, "Enter amount:");
        try {
            double amount = Double.parseDouble(amountStr);
            HashMap<String, Double> monthData = monthlySpendingData.getOrDefault(selectedMonth, new HashMap<>());
            monthData.put(category, monthData.getOrDefault(category, 0.0) + amount);
            monthlySpendingData.put(selectedMonth, monthData);
            updateSpendingTable();
            updateSummaryLabels();
            saveData();
            updateGraph((JPanel) tabbedPane.getComponentAt(1)); // Automatically refresh graph
            addTransaction(category, amount);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(frame, "Invalid amount.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void updateSpendingTable() {
        spendingModel.setRowCount(0);
        HashMap<String, Double> monthData = monthlySpendingData.getOrDefault(selectedMonth, new HashMap<>());
        for (Map.Entry<String, Double> entry : monthData.entrySet()) {
            spendingModel.addRow(new Object[]{entry.getKey(), entry.getValue()});
        }
    }

    private void updateGraph(JPanel graphPanel) {
        DefaultPieDataset dataset = new DefaultPieDataset();
        HashMap<String, Double> monthData = monthlySpendingData.getOrDefault(selectedMonth, new HashMap<>());
        for (Map.Entry<String, Double> entry : monthData.entrySet()) {
            dataset.setValue(entry.getKey(), entry.getValue());
        }

        JFreeChart chart = ChartFactory.createPieChart(selectedMonth + " Spending", dataset, true, true, false);
        ChartPanel chartPanel = new ChartPanel(chart);

        graphPanel.removeAll();
        graphPanel.add(chartPanel, BorderLayout.CENTER);
        graphPanel.revalidate();
        graphPanel.repaint();
    }

    private void updateAnnualGraph(JPanel graphPanel) {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (String month : getMonths()) {
            HashMap<String, Double> monthData = monthlySpendingData.getOrDefault(month, new HashMap<>());
            double totalMonthSpending = monthData.values().stream().mapToDouble(Double::doubleValue).sum();
            dataset.addValue(totalMonthSpending, "Expense", month);
        }

        JFreeChart chart = ChartFactory.createBarChart("Annual Spending", "Month", "Amount", dataset);
        ChartPanel chartPanel = new ChartPanel(chart);

        graphPanel.removeAll();
        graphPanel.add(chartPanel, BorderLayout.CENTER);
        graphPanel.revalidate();
        graphPanel.repaint();
    }

    private void addTransaction(String category, double amount) {
        String date = new Date().toString();
        transactionHistory.add(new Object[]{date, category, amount});
        updateTransactionTable();
    }

    private void updateTransactionTable() {
        transactionModel.setRowCount(0);
        for (Object[] transaction : transactionHistory) {
            transactionModel.addRow(transaction);
        }
    }

    private void updateSummaryLabels() {
        DecimalFormat df = new DecimalFormat("0.00");
        double totalExpense = monthlySpendingData.getOrDefault(selectedMonth, new HashMap<>()).values().stream().mapToDouble(Double::doubleValue).sum();
        double balance = income - totalExpense;

        totalExpenseLabel.setText("Total Expense: ৳" + df.format(totalExpense));
        balanceLabel.setText("Balance: ৳" + df.format(balance));
    }

    private void saveData() {
        String dataFileName = DATA_FILE_PREFIX + currentUser + ".dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(dataFileName))) {
            oos.writeObject(monthlySpendingData);
            oos.writeDouble(income);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadData() {
        String dataFileName = DATA_FILE_PREFIX + currentUser + ".dat";
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(dataFileName))) {
            monthlySpendingData = (HashMap<String, HashMap<String, Double>>) ois.readObject();
            income = ois.readDouble();
            updateSummaryLabels();
        } catch (IOException | ClassNotFoundException e) {
            monthlySpendingData = new HashMap<>();
            income = 0.0;
        }
    }

    private String[] getMonths() {
        return new String[]{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ExpenseTracker::new);
    }
}
Editor is loading...
Leave a Comment