lmari’s blog

Data analytics, machine learning & front end development

Budget App with ES6

  • Followup: Adapt to calculating owner's earnings:

    Owners earning =

    Net Income*
    + Depreciation & Amortization
    + Net Change: Accounts Receivable*
    + Net Change: Accounts Payable*
    + Income Tax
    + Maintenance Capital Expenditures**

  • or Free Cash Flow

    Net Cash Provided by Operating Activities
    + Purchase of Property and Equipment (a negative number)
    + Any Other Capital Expenditures for Maintenance and Growth (also negative numbers)

  • using the powerful "reduce" function

f:id:lmari:20190521165036j:plain

  • adding methods to list of functions
  • class keyword, name of class
  • console.log to check if code is working

f:id:lmari:20190521164919j:plain

Check code:

f:id:lmari:20190521164908j:plain

function UI(id){
this.id = id
}

class UI {
constructor(id) {
this.id = id;
}
}

app.js

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;
// console.log(this);

setTimeout(function() {
self.budgetFeedback.classList.remove('showItem');
}, 4000);
} 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');
}, 4000);
} 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();
// show balance
}
}
// 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 list
let expense = this.itemList.filter(function(item){
return item.id === id;
})
// show value
this.expenseInput.value = expense[0].title;
this.amountInput.value = expense[0].amount
// remove from 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 list
let tempList = this.itemList.filter(function(item){
return item.id !== id;
});
this.itemList = tempList;
this.showBalance();
}
}

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

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 click
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() {
eventListenters();
})