JSFiddle - React, Tailwind, and code Playground

by Pixie_Dust

HTML

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

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Book List app</title>
    <!-- fontAwesome script -->
    <script src="https://kit.fontawesome.com/39350fd9df.js"></script>
    <!-- bootstrap css -->
    <!-- <link rel="stylesheet" href="bootstrap.min.css" type="text/css"> -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
  </head>

  <body>
    <div class="container mt-4">

      <h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>

      <form action="#" id="book-form">
        <div class="form-group mb-2">
          <label for="title">Book Title</label>
          <input type="text" name="title" id="title" class="form-control">
        </div>
        <div class="form-group mb-2">
          <label for="author">Author Name</label>
          <input type="text" name="author" id="author" class="form-control">
        </div>
        <div class="form-group">
          <label for="book-id">Reference Id</label>
          <input type="text" name="title" id="bookId" class="form-control">
        </div>

        <input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
      </form>

      <table class="table table-striped mt-4">

        <thead>
          <tr>
            <th>Book Title</th>
            <th>Author Name</th>
            <th>Reference Id</th>
            <th class="text-warning"><small>Delete book</small></th>
          </tr>
        </thead>

        <tbody id="book-list"></tbody>
      </table>
    </div>

    <script src="app.js" type="text/javascript"></script>
  </body>

</html>

JavaScript

// Book class 
class Book {
  constructor(title, author, id) {
    this.bookName = title;
    this.authorName = author;
    this.bookId = id;
  }
}

// Dom class : handle user interface / dom
class Dom {
  static displayBooks() {
    const books = Store.getBooks();
    books.forEach((book) => Dom.addBookToList(book))
  }

  static addBookToList(bookInfo) {
    const tbody = document.querySelector('#book-list')
    const bookRow = document.createElement('tr');
    bookRow.innerHTML =
      `
        <tr>
            <td>${bookInfo.bookName}</td>
            <td>${bookInfo.authorName}</td>
            <td>${bookInfo.bookId}</td>
            <td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
        </tr>
        `
    tbody.appendChild(bookRow);
  }

  static deleteBook(target) {
    if (target.classList.contains('deleteBtn')) {
      target.parentElement.parentElement.remove()
      // show alert if user deletes a book
      Dom.showAlert('Book deleted successfully', 'warning');
    }
  }

  static showAlert(msg, className) {
    const alertBox = document.createElement('div');
    alertBox.className = `alert alert-${className} mb-3 p-2`;
    alertBox.appendChild(document.createTextNode(msg));

    const container = document.querySelector('.container');
    const form = document.querySelector('#book-form');

    // check whether if an alertBox already exist in the UI
    if (document.querySelector('.alert')) {
      // remove alerBox after an interval
      setTimeout(() => {
        document.querySelector('.alert').remove();
      }, 3000);
    } else {
      container.insertBefore(alertBox, form);
    }
  }

  static clearFields() {
    document.querySelector('#title').value = '';
    document.querySelector('#author').value = '';
    document.querySelector('#bookId').value = '';
  }
}


// Store class - deals with localStorage
class Store {
  static getBooks() {
    let books;
    if (localStorage.getItem('books') === null) {
      // if...