Javascript Budget Project for Intermediates




Hey guys in this post, we will create a Javascript budget project for intermediates. Follow this tutorial till the end to understand the javascript concepts. we will create this project step by step. The final version of the app is live on the internet.

Topics covered


This application involves the following topics –

  • Object Oriented JavaScript
  • JavaScript Class Object
  • JavaScript Constructor Functions
  • JavaScript Prototypal Inheritance
  • JavaScript CSS Manipulation
  • JavaScript DOM Manipulation

Complete source code


The below image shows you the project structure –

Screenshot-2021-06-18-at-7-36-41-PM

Add styles to the application


Create a main.css file and add the following content –

:root {
  --mainWhite: #f5f5f5f5;
  --mainDark: #333333;
  --mainGreen: #317b22;
  --mainRed: #b80c09;
  --mainBlue: #05668d;
}

body {
  background: var(--mainWhite);
  color: var(--mainDark);
}
.budget-feedback,
.expense-feedback {
  display: none;
}

.budget-form {
  border: 0.15rem solid var(--mainGreen);
  padding: 1rem;
  border-radius: 0.25rem;
}
.expense-form {
  border: 0.15rem solid var(--mainRed);
  padding: 1rem;
  border-radius: 0.25rem;
}
.budget-submit {
  background: transparent;
  border: 0.1rem solid var(--mainGreen);
  color: var(--mainGreen);
}
.expense-submit {
  background: transparent;
  border: 0.1rem solid var(--mainRed);
  color: var(--mainRed);
}
.expense-submit:hover {
  background: var(--mainRed);
  color: var(--mainWhite);
}
.budget-submit:hover {
  background: var(--mainGreen);
  color: var(--mainDark);
}

.budget-input {
  border: 0.05rem solid var(--mainGreen) !important;
}
.expense-input {
  border: 0.05rem solid var(--mainRed) !important;
}
.expense-amount,
.expense-title {
  color: var(--mainRed);
}
.edit-icon {
  color: var(--mainBlue);
  cursor: pointer;
  font-size: 1rem;
  text-decoration: none !important;
}
.delete-icon {
  color: var(--mainRed);
  cursor: pointer;
  font-size: 1rem;
  text-decoration: none !important;
}
.edit-icon:hover {
  color: var(--mainBlue);
}
.delete-icon:hover {
  color: var(--mainRed);
}
.showItem {
  display: block;
}
.info-title {
  font-size: 1.5rem;
}
.budget {
  font-size: 1.6rem;
  color: var(--mainGreen);
}
.expense {
  font-size: 1.6rem;
  color: var(--mainRed);
}
.balance {
  font-size: 1.6rem;
}
.budget-icon,
.expense-icon,
.balance-icon {
  font-size: 2.5rem;
  color: var(--mainBlue);
}
.showRed {
  color: var(--mainRed);
}
.showGreen {
  color: var(--mainGreen);
}
.showBlack {
  color: var(--mainDark);
}
@media screen and (min-width: 992px) {
  .budget {
    font-size: 2.6rem;
    color: var(--mainGreen);
  }
  .expense {
    font-size: 2.6rem;
    color: var(--mainRed);
  }
  .balance {
    font-size: 2.6rem;
  }
  .budget-icon,
  .expense-icon,
  .balance-icon {
    font-size: 3.5rem;
    color: var(--mainBlue);
  }
}
.list-item {
  flex: 0 0 33.33%;
  text-align: center;
}
.expense-item {
  height: 2rem;
}

Add scripts to the application


Create an app.js file and add the following content –

class UI {
  constructor() {
    this.budgetFeedback = document.querySelector(".budget-feedback");
    this.expenseFeedback = document.querySelector(".expense-feedback");
    this.budgetForm = document.getElementById("budget-form");
    this.budgetInput = document.getElementById("budget-input");
    this.budgetAmount = document.getElementById("budget-amount");
    this.expenseAmount = document.getElementById("expense-amount");
    this.balance = document.getElementById("balance");
    this.balanceAmount = document.getElementById("balance-amount");
    this.expenseForm = document.getElementById("expense-form");
    this.expenseInput = document.getElementById("expense-input");
    this.amountInput = document.getElementById("amount-input");
    this.expenseList = document.getElementById("expense-list");
    this.itemList = [];
    this.itemID = 0;
  }

  //submit budget method
  submitBudgetForm(){
      const value = this.budgetInput.value;
      if(value === '' || value < 0){
        this.budgetFeedback.classList.add('showItem');
        this.budgetFeedback.innerHTML = `<p>value cannot be empty or negative</p>`;
        const self = this;
        setTimeout(function(){
          self.budgetFeedback.classList.remove('showItem');
        }, 3000);
      } else {
        this.budgetAmount.textContent = value;
        this.budgetInput.value = '';
        this.showBalance();
      }
  }

  //show balance
  showBalance(){
    const expense = this.totalExpense();
    const total = parseInt(this.budgetAmount.textContent) - expense;
    this.balanceAmount.textContent = total;
    if(total < 0){
      this.balance.classList.remove('showGreen', 'showBlack');
      this.balance.classList.add('showRed');
    } else if(total > 0){
      this.balance.classList.remove('showRed', 'showBlack');
      this.balance.classList.add('showGreen');
    } else if(total === 0){
      this.balance.classList.remove('showRed', 'showGreen');
      this.balance.classList.add('showBlack');
    }
  }
  //submit expense form
  submitExpenseForm(){
    const expenseValue = this.expenseInput.value;
    const amountValue = this.amountInput.value;
    if(expenseValue === '' || amountValue === '' || amountValue < 0){
      this.expenseFeedback.classList.add('showItem');
      this.expenseFeedback.innerHTML = `<p>values cannot be empty or negative</p>`;
      const self = this;
      setTimeout(function(){
        self.expenseFeedback.classList.remove('showItem');
      }, 3000)
    } else {
      let amount = parseInt(amountValue);
      this.expenseInput.value = '';
      this.amountInput.value = '';

      let expense = {
        id: this.itemID,
        title: expenseValue,
        amount: amount
      }
      this.itemID++;
      this.itemList.push(expense);
      this.addExpense(expense);
      this.showBalance();

    }
  }

  //add expense
  addExpense(expense){
    const div = document.createElement('div');
    div.classList.add('expense');
    div.innerHTML = `<div class="expense-item d-flex justify-content-between align-items-baseline">

    <h6 class="expense-title mb-0 text-uppercase list-item">- ${expense.title}</h6>
    <h5 class="expense-amount mb-0 list-item">$${expense.amount}</h5>

    <div class="expense-icons list-item">

     <a href="#" class="edit-icon mx-2" data-id="${expense.id}">
      <i class="fas fa-edit"></i>
     </a>
     <a href="#" class="delete-icon" data-id="${expense.id}">
      <i class="fas fa-trash"></i>
     </a>
    </div>
   </div`;
   this.expenseList.appendChild(div);
  }

  //total expense
  totalExpense(){
    let total = 0;
    if(this.itemList.length > 0){
      total = this.itemList.reduce(function(acc, curr){
        acc += curr.amount;
        return acc;
      }, 0)
    } 
    this.expenseAmount.textContent = total;
    return total;
  }

  //edit expense
  editExpense(element){
    let id = parseInt(element.dataset.id);
    let parent = element.parentElement.parentElement.parentElement;
    //remove from DOM
    this.expenseList.removeChild(parent);
    //remove from the list
    let expense = this.itemList.filter(function(item){
      return item.id === id;
    })
    //show values
    this.expenseInput.value = expense[0].title;
    this.amountInput.value = expense[0].amount;
    //remove from the list
    let tempList = this.itemList.filter(function(item){
      return item.id !== id;
    })
    this.itemList = tempList;
    this.showBalance();
  }

  //delete expense
  deleteExpense(element){
    let id = parseInt(element.dataset.id);
    let parent = element.parentElement.parentElement.parentElement;
    //remove from DOM
    this.expenseList.removeChild(parent);
    //remove from the list
    let tempList = this.itemList.filter(function(item){
      return item.id !== id;
    })
    this.itemList = tempList;
    this.showBalance();
  }
}

function eventListeners(){
  const budgetForm = document.getElementById('budget-form');
  const expenseForm = document.getElementById('expense-form');
  const expenseList = document.getElementById('expense-list');

  //new instance of UI Class
  const ui = new UI();
  
  //budget form submit
  budgetForm.addEventListener('submit', function(event){
    event.preventDefault();
    ui.submitBudgetForm();
  })
  //expense form submit
  expenseForm.addEventListener('submit', function(event){
    event.preventDefault();
    ui.submitExpenseForm();

  })
  //expense list submit
  expenseList.addEventListener('click', function(event){
    if (event.target.parentElement.classList.contains('edit-icon')){
      ui.editExpense(event.target.parentElement);
    }else if (event.target.parentElement.classList.contains('delete-icon')){
      ui.deleteExpense(event.target.parentElement);
    }
  })
}

document.addEventListener('DOMContentLoaded', function(){
  eventListeners();
})

Add HTML to the application


Create an index.html file and add the following content –

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <!-- bootstrap css -->
 <link rel="stylesheet" href="./css/bootstrap.min.css">
 <!-- main css -->
 <link rel="stylesheet" href="./css/main.css">
 <!-- google fonts -->
 <link href="https://fonts.googleapis.com/css?family=Courgette" rel="stylesheet">

 <!-- font awesome -->
 <link rel="stylesheet" href="./css/all.css">
 <title>budget app</title>
 <style>
 </style>
</head>

<body>
 <div class="container-fluid">
  <div class="row">
   <div class="col-11 mx-auto pt-3">
    <!-- title -->
    <h3 class="text-uppercase mb-4">budget app</h3>
    <div class="row">
     <div class="col-md-5 my-3">
      <!-- budget feedback -->
      <div class="budget-feedback alert alert-danger text-capitalize">budget feedback</div>
      <!-- budget form -->
      <form id="budget-form" class=" budget-form">
       <h5 class="text-capitalize">please enter your budget</h5>
       <div class="form-group">
        <input type="number" class="form-control budget-input" id="budget-input">
       </div>
       <!-- submit button -->
       <button type="submit" class="btn text-capitalize budget-submit" id="budget-submit">calculate</button>
      </form>
     </div>
     <div class="col-md-7">
      <!-- app info -->
      <div class="row my-3">
       <div class="col-4 text-center mb-2">
        <h6 class="text-uppercase info-title">budget</h6>
        <span class="budget-icon"><i class="fas fa-money-bill-alt"></i></span>
        <h4 class="text-uppercase mt-2 budget" id="budget"><span>$ </span><span id="budget-amount">0</span></h4>
       </div>
       <div class="col-4 text-center">
        <h6 class="text-uppercase info-title">expenses</h6>
        <span class="expense-icon"><i class="far fa-credit-card"></i></span>
        <h4 class="text-uppercase mt-2 expense" id="expense"><span>$ </span><span id="expense-amount">0</span></h4>
       </div>
       <div class="col-4 text-center">
        <h6 class="text-uppercase info-title">balance</h6>
        <span class="balance-icon"><i class="fas fa-dollar-sign"></i></span>
        <h4 class="text-uppercase mt-2 balance" id="balance"> <span>$ </span><span id="balance-amount">0</span></h4>
       </div>
      </div>
     </div>
    </div>

    <div class="row">
     <div class="col-md-5 my-3">
      <!-- expense feedback -->
      <div class="expense-feedback alert alert-danger text-capitalize">expense feedback</div>
      <!-- expense form -->
      <form id="expense-form" class=" expense-form">
       <h5 class="text-capitalize">please enter your expense</h5>
       <div class="form-group">
        <input type="text" class="form-control expense-input" id="expense-input">
       </div>
       <h5 class="text-capitalize">please enter expense amount</h5>
       <div class="form-group">
        <input type="number" class="form-control expense-input" id="amount-input">
       </div>
       <!-- submit button -->
       <button type="submit" class="btn text-capitalize expense-submit" id="expense-submit">add expense</button>
      </form>
     </div>
     <div class="col-md-7 my-3">
      <!-- expense list -->
      <div class="expense-list" id="expense-list">

       <div class="expense-list__info d-flex justify-content-between text-capitalize">
        <h5 class="list-item">expense title</h5>
        <h5 class="list-item">expense value</h5>
        <h5 class="list-item"></h5>
       </div>
       <!-- single expense -->

       <!-- <div class="expense">
        <div class="expense-item d-flex justify-content-between align-items-baseline">

         <h6 class="expense-title mb-0 text-uppercase list-item">- title</h6>
         <h5 class="expense-amount mb-0 list-item">amount</h5>

         <div class="expense-icons list-item">

          <a href="#" class="edit-icon mx-2" data-id="${expense.id}">
           <i class="fas fa-edit"></i>
          </a>
          <a href="#" class="delete-icon" data-id="${expense.id}">
           <i class="fas fa-trash"></i>
          </a>
         </div>
        </div>

       </div> -->

       <!-- end of single expense -->

      </div>
     </div>
    </div>




   </div>
  </div>
 </div>




 <!-- jquery -->
 <script src="./js/jquery-3.3.1.min.js"></script>
 <!-- bootstrap js -->
 <script src="./js/bootstrap.bundle.min.js"></script>
 <!-- script js -->
 <script src="./js/app.js"></script>
</body>

</html>

Screenshots


Screenshot-2021-06-18-at-7-47-44-PM

Download the complete source code from github repository

Original source https://jsbeginners.com/javascript-budget-app/

That’s it for this post. Hope you liked it, if you did then please share this with your friends and colleagues. Also, share this post in your social media profiles. Thanks, I will see you in the next post.



Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

Leave a Reply