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>Todo List App</title>
    <!-- Custom css -->
    <link rel="stylesheet" href="style.css">
    <!--Google fonts -->
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&display=swap" rel="stylesheet">
    <!-- fontawesome script-->
    <script src="https://kit.fontawesome.com/39350fd9df.js"></script>
  </head>

  <body>

    <div class="main-container">
      <h2 class="title">Todo App</h2>
      <div class="container">
        <div class="input-group">
          <input type="text" id="todoInput" placeholder="Enter new task...">
          <a href="#" class="btn addBtn"><i class="fas fa-plus"></i></a>
        </div>
        <table class="taskLister">
          <thead>
            <tr>
              <th>Status</th>
              <th>Task</th>
              <th>Edit</th>
              <th>Delete</th>
            </tr>
          </thead>
          <tbody id="tasks"></tbody>
        </table>
      </div>
    </div>

    <!-- Custom script -->
    <script src="app.js"></script>
  </body>

</html>

CSS

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    text-decoration: none;
    list-style: none;
}

:root {
    --primary-color: #143d59;
    --bg-color: #f4b41a;
    --text-font: Poppins;
    --round: 5px;
}

body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.btn {
    /* min-width: 20%; -- why is this not working? */
    padding: .8em 2em;
    font-size: 1.25em;
    font-weight: bold;
    border-radius: var(--round);
    color: var(--bg-color);
    background-color: var(--primary-color);
}

.main-container {
    min-width: 50vw;
    min-height: 75vh;
    padding: 0 2em;
    background-color: var(--bg-color);
    border-radius: var(--round);
}

.main-container .title {
    padding-top: .8em;
    color: var(--primary-color);
    font-size: 2em;
    font-family: var(--text-font);
    text-transform: uppercase;
    text-align: center;
}

.main-container #todoInput {
    margin-top: 1em;
    padding: .8em;
    border: transparent;
    font-size: 1.25em;
    min-width: 80%;
    border-radius: var(--round);
    outline: transparent;
}

.main-container #todoInput:focus {
    box-shadow: 0px 0px 0px 1px #1c577e;
}

.main-container .container {
    text-align: center;
}

.addBtn {
    padding: .8em 1em;
    transition: .3s linear;
}
.addBtn:hover {
    background-color: #182c3a;
    color: #f5b00e;
}

.taskLister {
    margin-top: 2em;
    border-collapse: collapse;
    background-color: #fff;
    min-width: 100%;
    font-size: 1.15em;
}

.taskLister th {
    background-color: #182c3a;
    color: var(--bg-color);
}

.taskLister th , .taskLister td{
    padding: .8em 1em;
}

.taskLister #tasks tr:nth-child(even) {
    background-color: #e7e7e7;
}

/* standalone styles */
#editBtn , #deleteBtn, #saveBtn{
    background-color: transparent;
    font-size: 1.15em;
    padding: .6em .8em;
    cursor: pointer;
}
.statusIcon {
    font-weight: bold;
    color: rgb(48, 158, 81);
}

td.task {
    opacity: .6;
...

JavaScript

const taskBtn = document.querySelector('.addBtn');
taskBtn.addEventListener('click', event => {
  UI.addTask(event.currentTarget.previousElementSibling.value);
});

class UI {
  // dummy data; for now.
  static displayTasks() {
    const tasks = ['Take out trash', 'Do laundry'];

    tasks.forEach(task => UI.addTask(task));
  }

  static addTask(task) {
    const tbody = document.querySelector('#tasks');

    const taskRow = document.createElement('tr');
    taskRow.className += 'task';
    taskRow.innerHTML = `
            <td><i class="far fa-check-circle complete"></i></td>
            <td>${task}</td>
            <td><a href="#" class="btn" id="editBtn"><i class="fas fa-edit edit"></i></a></td>
            <td><a href="#" class="btn" id="deleteBtn"><i class="fas fa-trash delete"></i></a></td>
        `;
    tbody.appendChild(taskRow);
    document.querySelector('#todoInput').value = '';
  }

  static taskEvents(eventTarget) {
    const targetClassName = eventTarget.classList
    if (targetClassName.contains('complete')) {
      targetClassName.toggle('statusIcon');
      eventTarget.parentElement.nextElementSibling.classList.toggle('task');
    } else if (targetClassName.contains('edit')) {
      const saveBtn = document.createElement('a');
      saveBtn.className = "btn";
      saveBtn.id = "saveBtn";
      saveBtn.innerHTML = '<i class="fas fa-save save"></i>';

      eventTarget.parentElement.replaceWith(saveBtn);
      //replace edit button with save button 
      console.log(eventTarget.parentElement);
      // Expected output : <a href="#" class="btn" id="saveBtn"><i class="fas fa-save save"></i></a>
      // output shown : <a href="#" class="btn" id="editBtn"><i class="fas fa-save edit"></i></a>

      const taskContent = eventTarget.parentElement.parentElement.previousElementSibling;
      // Expected to get <td>Task content...</td>
      // shown output : null , i think that line 40 affected the it's parent, it doesn't have a prent now
     ...