Build a Payroll Web App using HTML CSS – Bootstrap 5 & JavaScript

Web Development
Build a Payroll Web App using JavaScript

In this web development tutorial we are goin to create a payroll web application using HTML CSS / Bootstrap 5 for styling and JavaScript for the logic. We are also going to store data to session & local storage from where we are going to extract it and use it to calculate the total worked hours for one entire month. So lets get started with Building a Payroll Web App using JavaScript.

Steps:
1 – Create the payroll table in HTML using Bootstrap 5
2 – Hide and display table element using javascript and animation with CSS
3 – Create the employee data base using JSON and “random Name generator”
4 – Populate table using async await by load JSON data and display it to the DOM using map and join method
5 – Calculate Maximum Wage and Minimum Wage using the js Math method
6 – Calculate Average Wage using the js reduce method
7 – Calculate the months pay forEach employee by adding validation using condition if else statement, forEach loop and keyUp eventListener
7.1 – Save Data to browser local storage and / or session storage
8 – Get the total amount of payout for a specific month using the JS map method, filter method, parseFloat and substring and display it to the DOM

Useful Links:

Bootstrap 5 CDN

You can also copy the code for this project “Build a Payroll Web App using JavaScript” from below and just follow along if you wish

1 Payroll Web App HTML code:

 <h2 class="display-2 text-center my-5">Employee Payroll</h2>
    <div class="container-md text-center">
      <!--? Button to activate the table -->
      <button class="btn btn-lg btn-primary text-center" id="NewPayroll">
        New Payroll
      </button>
      <!--? Payroll Table -->
      <table
        id="PayrollTable"
        class="table table-striped table-hover text-info shadow"
      >
        <thead>
          <tr class="text-dark">
            <th scope="col">#</th>
            <th scope="col">First Name</th>
            <th scope="col">Last Name</th>
            <th scope="col">Hourly Wage</th>
            <th scope="col">Hours Worked</th>
            <th scope="col">Monthly Pay</th>
          </tr>
        </thead>
        <tbody id="Employees-table">
          <!-- <tr>
          <th scope="row">1</th>
          <td>Mark</td>
          <td>Otto</td>
          <td>@mdo</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
        </tr>
        <tr>
          <th scope="row">3</th>
          <td colspan="2">Larry the Bird</td>
          <td>@twitter</td>
        </tr> -->
        </tbody>
        <tfoot id="Summery" class="fw-bold text-dark">
          <tr>
            <th scope="row">Summery</th>
            <td class="text-success">Max : <span id="Max-wage">$00</span></td>

            <td class="text-danger">Min : <span id="Min-wage">$00</span></td>

            <td class="text-primary">Avg : <span id="Avg-wage">$00</span></td>
            <td><span id="Total-WH">0000 h</span></td>
            <td><span id="Total-pay">$ 0000 </span></td>
          </tr>
        </tfoot>
      </table>
    </div>

2 Payroll Web App CSS code:

/* hide Table  */

#PayrollTable {
  display: none;
  animation: fade 0.3s ease;
}
@keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

Payroll Web App JSON data code:

[
  {
    "id": "1",
    "firstName": "Laura",
    "lastName": "Storm",
    "hw": 14.46
  },
  {
    "id": "2",
    "firstName": "Jacob",
    "lastName": "Thornton",
    "hw": 19.47
  },
  {
    "id": "3",
    "firstName": "Zanna",
    "lastName": "Tatyana",
    "hw": 17.31
  },
  {
    "id": "4",
    "firstName": "Fábia",
    "lastName": "Linda",
    "hw": 15.3
  },
  {
    "id": "5",
    "firstName": "Ganbold ",
    "lastName": "Anand",
    "hw": 23.25
  },
  {
    "id": "6",
    "firstName": "Grier",
    "lastName": "Seneca",
    "hw": 34.31
  },
  {
    "id": "7",
    "firstName": "Rosalie",
    "lastName": "Kenji",
    "hw": 17.18
  },
  {
    "id": "8",
    "firstName": "Aurelia",
    "lastName": "Widald",
    "hw": 21.32
  },
  {
    "id": "9",
    "firstName": "Motya",
    "lastName": "Yehonatan",
    "hw": 54.78
  },
  {
    "id": "10",
    "firstName": "Ihintza",
    "lastName": "Hildefons",
    "hw": 18.2
  }
]

3 Payroll Web app JavaScript code:

// Get elements

//Todo: Hide Button and Display Table
const newPayrollBtn = document.getElementById("NewPayroll");
newPayrollBtn.addEventListener("click", () => {
  const payrollTable = document.getElementById("PayrollTable");
  // console.log(payrollTable);

  payrollTable.style.display = "table";
  newPayrollBtn.style.display = "none";
});

//Todo: Get Data from JSON file
//* Employee First & Last Name
//* Hourly Wage
let personalList = [];

const loadEmployees = async () => {
  try {
    const res = await fetch("data/employees.json");
    personalList = await res.json();

    // console.log(personalList);

    displayEmployees(personalList);
  } catch (err) {
    console.error(err);
  }
};

// todo:
const displayEmployees = (employee) => {
  const employeesTable = employee
    .map((employee) => {
      return `
<tr>

<th scope="row" >${employee.id}</th>
<td>${employee.firstName}</td>
<td>${employee.lastName}</td>
<td>$${employee.hw}</td>
<td><input type="number" class="hours-worked" style="width:60px"  min="0"/> h</td>
<td class='monthly-pay fw-bold' > </td>

</tr>
        

      `;
    })
    .join("");

  document.getElementById("Employees-table").innerHTML = employeesTable;

  //! -----------------------------------------------------

  monthlyPay();

  // console.log(employee);

  //todo: 5+6 Outputs Max, Min & Avg
  //* Get Hourly Wage
  const getEmployeesHW = employee.map((employee) => employee.hw);

  // console.log(getEmployeesHW);

  //* Maximum Wage
  let maxHW = calcMaxWage(getEmployeesHW);
  document.getElementById("Max-wage").innerText = "$" + maxHW;

  //* Minimum Wage
  let minHW = calcMinWage(getEmployeesHW);
  document.getElementById("Min-wage").innerText = "$" + minHW;

  //* Average Wage
  // get total amount of hourly wages
  const getTotalHW = (total, hw) => total + hw;

  const getAvgHW = (arr) => arr.reduce(getTotalHW, 0) / arr.length;

  // console.log(getAvgHW(getEmployeesHW));

  let avgHW = getAvgHW(getEmployeesHW).toFixed(2);
  document.getElementById("Avg-wage").innerText = "$" + avgHW;
};

loadEmployees();

function monthlyPay() {
  const hoursWorked = document.querySelectorAll(".hours-worked");
  // console.log(hoursWorked);

  hoursWorked.forEach((workHour) => {
    workHour.addEventListener("keyup", (e) => {
      // console.log(e.target.value);
      //! Condition Action
      if (e.target.value === "" || e.target.value <= 0) {
        return;
      } else {
        // console.log("moths pay");
        if (e.key === "Enter") {
          // console.log(e.target.value);
          // console.log(e.target.parentElement.parentElement.children[3].innerText);
          const hour = e.target.value;
          const hourlyWage = Number(
            e.target.parentElement.parentElement.children[3].innerText.substring(
              1
            )
          );

          // console.log(e.target.parentElement.parentElement.children[5]);

          let monthlyPay = e.target.parentElement.parentElement.children[5];

          const calcMonthlyPay = (hour * hourlyWage).toFixed(2);

          monthlyPay.innerText = "$" + calcMonthlyPay;

          //todo: Set to Local / Session  storage

          saveData(hour);

          //* Get Total Payouts

          getTotalPayouts();
        }
      }
    });
  });
}

// Todo: Input
//* Hours Worked

//todo: Output
//* Monthly Pay = Hourly Wage * Hours Worked

//* Maximum Wage
function calcMaxWage(arr) {
  return Math.max(...arr);
}
//* Minimum Wage

function calcMinWage(arr) {
  return Math.min(...arr);
}

//* Total

//todo: Set to Local / Session  storage

function saveData(hour) {
  let hours;

  if (sessionStorage.getItem("hours") === null) {
    hours = [];
  } else {
    hours = JSON.parse(sessionStorage.getItem("hours"));
  }

  hours.push(hour);

  sessionStorage.setItem("hours", JSON.stringify(hours));

  // console.log(hours);

  const newHours = hours.map((hour) => parseInt(hour));
  // console.log(newHours);

  let totalHours = newHours.reduce(calcTotal, 0);

  // console.log(totalHours);
  document.getElementById("Total-WH").innerText = totalHours + " h";
}

// ? uFunc for calculating  total amount!

const calcTotal = (total, num) => {
  return total + num;
};

function getTotalPayouts() {
  const allMonthlyPays = document.querySelectorAll(".monthly-pay");

  let arrayOfPayouts = Array.from(allMonthlyPays);
  // console.log(arrayOfPayouts);

  let newPayout = arrayOfPayouts.map((payout) =>
    parseFloat(payout.innerHTML.substring(1))
  );

  // console.log(newPayout);

  // * Return array elements with values
  newPayout = newPayout.filter((payout) => payout);

  // console.log(newPayout);

  let calculateTotalPay = newPayout.reduce(calcTotal, 0);

  document.getElementById("Total-pay").innerText =
    "$" + calculateTotalPay.toFixed(2);
}

View the full video tutorial

Become a web developer!

Learn HTML CSS & Sass JavaScript Bootstrap and more…

Web development

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.