Open In App

Build an Expense Tracker using JavaScript

Last Updated : 22 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will demonstrate the creation of a basic expense tracker web page using JavaScript. An Expense Tracker can be useful in keeping a record of the expenditure, you can maintain a list of expenses along with individual and total amounts. Just enter a name and amount and you can store all data together. Also, there exists a summary of total income, expenses, and the remaining balance.

On completion, the expense tracker will look like the following image:

Screenshot-from-2023-08-21-14-26-12

Prerequisites:

Approach:

  • Create an HTML structure for the expense tracker with an HTML table for showing expenses and input, a button for accepting user input, and using div & span along with relevant class names.
  • Design the structure with CSS properties like display type for items layout, width, margins, padding for spaces, box shadow for card type view, background color, font size, font weight, etc. for elements Classes and IDs.
  • In JavaScript, define an addItem() function that triggers on click event and involves HTML DOM method document.getElementById() to access the input.
  • Also, define a function loadItems() that takes in expense component as input and uses HTML DOM table methods to show them to the User Interface.
  • You can also have a pre-listed expanses array which can be displayed using the array.map method.

 

Example: This example illustrates the basic expanse tracker using Javascript.

HTML




<!-- index.html-->
  
<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" 
          content="width=device-width, 
                   initial-scale=1.0" />
    <link rel="stylesheet" 
          href="style.css" />
    <title>Expense Tracker</title>
</head>
  
<body>
    <div>
        <h1 style="color: green;">
              GeeksforGeeks
          </h1>
        <h3>Expense Tracker Using JavaScript</h3>
    </div>
    <div class="summary">
        <div>
            <h1>✔ Balance:
                <span id="updatedBal">
                      7000
                  </span>
            </h1>
        </div>
        <br />
        <div class="total">
            <div>
                Total Income:
                <div>
                    <h2 style="color: green;"
                        id="updatedInc">
                        25000
                    </h2>
                </div>
            </div>
            <hr class="verticle" />
            <div>
                Total Expenses:
                <div>
                    <h2 style="color: red;" 
                        id="updatedExp">
                        18000
                    </h2>
                </div>
            </div>
        </div>
    </div>
    <div class="root">
        <div id="items">
            <h2>Expenses</h2>
            <table id="table">
                <tr class="titles">
                    <th>S.no.</th>
                    <th>Name</th>
                    <th>Amount</th>
                    <th>Type</th>
                    <th>Delete</th>
                </tr>
            </table>
        </div>
        <hr class="vertical" />
        <div id="new">
            <h2>Add new</h2>
  
            <div class="inputs">
                <div class="inputitem">
                    <p style="width: 9rem">
                        Entry type:
                    </p>
                    <select id='itemType'>
                        <option value="0">Expense</option>
                        <option value="1">Income</option>
                    </select>
                </div>
                <div class="inputitem">
                    <p style="width: 9rem">Name:</p>
                    <input id="name" 
                           type="text"
                           value="" 
                           placeholder="name" />
                </div>
                <div class="inputitem">
                    <p style="width: 9rem">Amount:</p>
                    <input value="0" 
                           id="amount"
                           name="mod" 
                           type="number" 
                           placeholder="amount" />
                </div>
            </div>
            <button onclick="addItem()">
                Add Expense
            </button>
        </div>
    </div>
    <script src="script.js"></script>
</body>
  
</html>


CSS




/* style.css*/
  
/* Style to body tag*/
body {
    display: flexbox;
    text-align: center;
    align-items: center;
}
  
/* Style to expense summary */
.summary {
    width: 25rem;
    display: flex;
    flex-direction: column;
    text-align: center;
    margin: auto;
    margin-bottom: 40px;
    padding: 1%;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
}
  
  
.total {
    display: flex;
    flex-direction: row;
    margin: auto;
}
  
.total>div {
    width: 200px;
}
  
/* Style for the expense table and input form*/
.root {
    width: fit-content;
    background-color: white;
    display: flex;
    margin: auto;
    padding: 2%;
    padding-top: 1%;
    justify-content: center;
    text-align: center;
    border-width: 6px;
    border: 6px grey;
    box-sizing: content-box;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
    min-height: 30vh;
}
  
  
/* Style for the verticle bar*/
.vertical {
    color: rgb(35, 35, 106);
    margin: 0 2%;
    border-width: 2px;
}
  
/* Style for table*/
#table {
    border-collapse: collapse;
    width: 50vw;
    border: 1px solid #ddd;
    font-size: 18px;
}
  
/* Table */
#table th,
#table td {
    text-align: left;
    padding: 12px;
}
  
/* Table row */
#table tr {
    border-bottom: 1px solid #ddd;
}
  
/* Headings*/
#table tr.titles {
    background-color: lightgreen;
}
  
/* Style for each input item */
.inputitem {
    display: flex;
    flex-direction: row;
    font-weight: bolder;
    font-size: large;
    padding: 1%;
}
  
input,
select,
option {
    padding: 2%;
    border-radius: 5px;
    margin: 2%;
}
  
button {
    font-size: large;
    border-radius: 5px;
    padding: 1%;
}
  
.zoom {
    color: black;
    transition: transform .2s;
  
}
  
.zoom:hover {
    transform: scale(1.23);
  
    color: green;
}


Javascript




// script.js
  
// Initial Data
let tableEntries = [
    { type: 1, name: "income", amount: 25000 },
    { type: 0, name: "rent", amount: 18000 },
    { type: 0, name: "food", amount: 5000 },
];
  
// Function to update data expense summary
function updateSummary() {
    let totalIncome = tableEntries.reduce((t, e) => {
        if (e.type === 1) t += e.amount;
        return t;
    }, 0);
    let totalExpense = tableEntries.reduce((ex, e) => {
        if (e.type === 0) ex += e.amount;
        return ex;
    }, 0);
    updatedInc.innerText = totalIncome;
    updatedExp.innerText = totalExpense;
    updatedBal.innerText = totalIncome - totalExpense;
}
  
  
// Function to add new entry to the dataset and expense table 
function addItem() {
    let type = itemType.value;
    let name = document.getElementById("name");
    let amount = document.getElementById("amount");
  
    // Input validation
    if (name.value === "" || Number(amount.value) === 0)
        return alert("Incorrect Input");
    if (Number(amount.value) <= 0)
        return alert(
            "Incorrect amount! can't add negative"
        );
  
    // Push new data
    tableEntries.push({
        type: Number(type),
        name: name.value,
        amount: Number(amount.value),
    });
  
    updateTable();
    name.value = "";
    amount.value = 0;
}
  
// Function to load all entry in the expense table
function loadItems(e, i) {
    let cls;
  
    let table = document.getElementById("table");
    let row = table.insertRow(i + 1);
    let cell0 = row.insertCell(0);
    let cell1 = row.insertCell(1);
    let cell2 = row.insertCell(2);
    let c3 = row.insertCell(3);
    let c4 = row.insertCell(4);
    cell0.innerHTML = i + 1;
    cell1.innerHTML = e.name;
    cell2.innerHTML = e.amount;
    c4.innerHTML = "☒";
    c4.classList.add("zoom");
    c4.addEventListener("click", () => del(e));
    if (e.type == 0) {
        cls = "red";
        c3.innerHTML = "➚";
    } else {
        cls = "green";
        c3.innerHTML = "➘";
    }
    c3.style.color = cls;
}
  
// Clear the table before updation
function remove() {
    while (table.rows.length > 1) table.deleteRow(-1);
}
  
// Function to delete a specific entry
function del(el) {
    remove();
    tableEntries = tableEntries.filter(
        (e) => e.name !== el.name
    );
    tableEntries.map((e, i) => loadItems(e, i));
    updateSummary();
}
  
// To render all entries
function updateTable() {
    remove();
    tableEntries.map((e, i) => {
        loadItems(e, i);
    });
    updateSummary();
}
  
updateTable();


Output:

Peek-2023-08-21-14-42



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads