Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Test School Vanilla JS

on:
pull_request_target::
pull_request_target:
types: [opened, synchronize, reopened]
branches: ["main", "master"]

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Buget Tracker</title>
<title>Budget Tracker</title>
<link rel="stylesheet" href="styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Expand Down Expand Up @@ -143,6 +143,7 @@ <h3>Manage Categories</h3>
<div class="tabs">
<button class="tab-btn active"
data-tab="transactions">Transactions</button>
<button class="tab-btn" data-tab="goals">Goals</button>
</div>

<div class="tab-content active" id="transactions-tab">
Expand Down Expand Up @@ -187,5 +188,7 @@ <h3>Savings Goals</h3>
</div>

<script type="module" src="script.js"></script>
<script src="utilities/setGoalsScript.js"></script>
<script type="module" src="utilities/generateReport.js"></script>
</body>
</html>
117 changes: 90 additions & 27 deletions src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,73 @@ let transactions = getTransactionsFromStorage();
function addTransaction(e, descriptionEl, amountEl, categoryEl, dateEl) {
e.preventDefault();

const amount = parseFloat(amountEl.value);

const description = descriptionEl.value;
// Enhanced input validation
const description = descriptionEl.value.trim();
const amountStr = amountEl.value.trim();
const category = categoryEl.value;
const date = dateEl.value;

// Validate all inputs thoroughly
if (!description) {
alert("Please enter a description for the transaction.");
descriptionEl.focus();
return;
}

if (!amountStr) {
alert("Please enter an amount for the transaction.");
amountEl.focus();
return;
}

const amount = parseFloat(amountStr);
if (isNaN(amount)) {
alert("Please enter a valid number for the amount.");
amountEl.focus();
return;
}

if (amount === 0) {
alert("Amount cannot be zero. Please enter a non-zero value.");
amountEl.focus();
return;
}

if (!category) {
alert("Please select a category for the transaction.");
categoryEl.focus();
return;
}

if (!date) {
alert("Please select a date for the transaction.");
dateEl.focus();
return;
}

// Create transaction object
const newTransaction = {
id: generateID(),
description,
amount,
category,
date,
};

transaction.push(newTransaction);
// Add to transactions array
transactions.push(newTransaction);
updateLocalStorage();

// Reset form with improved user experience
descriptionEl.value = "";
amountEl.value = "";
categoryEl.value = "Other";
dateEl.valueAsDate = new Date(); // Reset to today's date instead of clearing

// Focus on the description field for the next entry
descriptionEl.focus();

console.log("Transaction added:", newTransaction);
}

// Generate unique ID
Expand All @@ -94,21 +146,23 @@ function removeTransaction(id) {
function updateValues(balanceEl, incomeEl, expenseEl) {
const amounts = transactions.map((transaction) => transaction.amount);

const total = amounts.reduce((acc, amount) => {
return (acc = amount);
}, 0);

// Calculate income (sum of all positive amounts)
const income = amounts
.filter((amount) => amount > 0)
.reduce((acc, amount) => acc + amount, 0);

// Calculate expenses (sum of all negative amounts as a positive number)
const expense = amounts
.filter((amount) => amount < 0)
.reduce((acc, amount) => acc - amount, 0);
.reduce((acc, amount) => acc + Math.abs(amount), 0);

// Calculate balance as income minus expenses
const balance = income - expense;

balanceEl.textContent = `Rs ${total}`;
incomeEl.textContent = `+Rs ${income}`;
expenseEl.textContent = `-Rs ${Math.abs(expense)}`;
// Update UI elements with formatted values
balanceEl.textContent = `Rs ${balance.toFixed(2)}`;
incomeEl.textContent = `+Rs ${income.toFixed(2)}`;
expenseEl.textContent = `-Rs ${expense.toFixed(2)}`;
}

// Add transactions to DOM
Expand All @@ -117,7 +171,8 @@ function addTransactionDOM(transaction, transactionListEl) {

const item = document.createElement("li");

item.className = transaction.category === "income" ? "expense" : "income";
// Fix incorrect class assignment - base it on amount instead of category name
item.className = transaction.amount < 0 ? "expense" : "income";

const detailsDiv = document.createElement("div");
detailsDiv.className = "details";
Expand Down Expand Up @@ -275,27 +330,38 @@ function generateReport() {
.filter((t) => t.amount > 0)
.reduce((acc, t) => acc + t.amount, 0);

// Fix: Filter for negative amounts for expenses
const totalExpense = transactions
.filter((t) => t.amount > 0)
.reduce((acc, t) => acc + t.amount, 0);
.filter((t) => t.amount < 0)
.reduce((acc, t) => acc + Math.abs(t.amount), 0);

const balance = totalIncome - totalExpense;

// Consistent decimal formatting for all monetary values
reportText += `Total Income: Rs ${totalIncome.toFixed(2)}\n`;
reportText += `Total Expense: Rs ${Math.abs(totalExpense).toFixed(2)}\n`;
reportText += `Total Expense: Rs ${totalExpense.toFixed(2)}\n`;
reportText += `Balance: Rs ${balance.toFixed(2)}\n\n`;

// Category breakdown
reportText += "Expense Breakdown by Category:\n";

const categorySummary = {};

// Initialize all categories with zero
transactions.forEach((t) => {
if (t.amount < 0 && !categorySummary[t.category]) {
categorySummary[t.category] = 0;
}
});

// Sum expenses by category
transactions.forEach((t) => {
if (t.amount < 0) {
categorySummary[t.category] += Math.abs(t.amount);
}
});

// Format and display each category
for (const category in categorySummary) {
reportText += `${category}: Rs ${categorySummary[category].toFixed(2)}\n`;
}
Expand Down Expand Up @@ -403,8 +469,8 @@ function deleteCategory(categoryName) {

// Update transactions with this category to "Other" or first available category
const defaultCategory = "Other";
const transactions = getTransactionsFromStorage();


// Use the global transactions variable instead of redeclaring it
transactions.forEach((transaction) => {
if (transaction.category === categoryName) {
transaction.category = defaultCategory;
Expand All @@ -431,18 +497,15 @@ function updateCategoryDropdowns(categoryDropdowns) {
const currentValue = dropdown.value;
dropdown.innerHTML = "";

// Add all categories
// Add all categories without unnecessary formatting
categories.forEach((category) => {
dropdown.insertAdjacentHTML(
"beforeend",
`<option value="${category.toLowerCase()}">${category}</option>`
);
const option = document.createElement("option");
option.value = category;
option.textContent = category;
dropdown.appendChild(option);
});

if (
currentValue &&
dropdown.querySelector(`option[value="${currentValue}"]`)
) {
if (currentValue && dropdown.querySelector(`option[value="${currentValue}"]`)) {
dropdown.value = currentValue;
}
});
Expand Down
12 changes: 10 additions & 2 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,19 @@ header {
width: 95%;
max-width: 1200px;
margin: 0 auto;
/* Bug #23: display should flex */
display: flex; /* Adding display flex to properly structure the layout */
flex-wrap: wrap;
gap: 20px;
}

/* Enhancing UI structure by defining a grid layout for the main container */
.main-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
gap: 20px;
}

.dashboard {
flex: 1;
min-width: 300px;
Expand Down Expand Up @@ -287,8 +295,8 @@ select {

.tab-content.active {
display: block;
/* Bug #24: overflow-y should be set to auto */
height: 370px;
overflow-y: auto;
}

/* Transaction List */
Expand Down