</> Code Review

The application manages tasks using the following function groups:

  • Data Management
    1. Build Checklist
  • Business Logic
    1. Add Tasks
    2. Mark Tasks as Complete / Incomplete
    3. Delete Tasks
  • Data Display
Click the section links below to learn more about the code.

Build Checklist

This function is the trigger point of the application. Helper functions (getLocalStorage, setLocalStorage) are used to access local storage.

Lines 8 - 10 Return seed data for testing purposes

Line 13 The variable modelData is the focal point of the application as it the holding space for display data.

// Build Checklist
function buildList() {
  // Change source to LocalStorage
  // Use seed data if local storage is empty (for testing only)
  let local = getLocalStorage();

  // This for TESTING PURPOSE (Comment out later)
  if (local.length === 0) {
    setLocalStorage(seedData);
    local = getLocalStorage();
  }

  modelData = local;

  displayData(modelData);
}
// Get Local Storage
function getLocalStorage() {
  return JSON.parse(localStorage.getItem('taskArray')) || [];
}
// Set Local Storage
function setLocalStorage(array) {
  localStorage.setItem('taskArray', JSON.stringify(array));
}

Add Task

The Add Task function creates an object which is then pushed to the task array. The array is then saved to local storage.

Lines 20 - 23 Both date fields use a helper function (setDateTime) to adjust for the impact of time.

// Add Task
function addTask() {

  // Get array from local storage
  const tasks = getLocalStorage();

  // Task Object
  const task = {};

  // Set complete to false
  task['complete'] = false;

  //     Get UUID
  task['id'] = getUUID();

  // Retrieve task from modal form
  task['task'] = document.getElementById('newTask').value;

  //     Generate Today's Date - https://stackoverflow.com/questions/3894048/what-is-the-best-way-to-initialize-a-javascript-date-to-midnight
  task['createdDate'] = setDateTime(new Date());

  // Retrieve Due Date from Form
  task['dueDate'] = setDateTime(document.getElementById('newDueDate').value);

  // Push to array
  tasks.push(task);

  // Set array in local storage
  setLocalStorage(tasks);

  // Set modelData to new data
  modelData = getLocalStorage();

  // Reset form
  document.getElementById('newTaskForm').reset();

  // Display Data
  displayData(modelData);
}
// Set Date and Time
function setDateTime(dateInput) {
  let date = dateInput;
  let mthAdjust = 1;

  if (typeof dateInput === 'string') {
    let [year, month, day] = dateInput.split('-');
    mthAdjust = 0;
    date = new Date(year, month, day);
  }

  const day = date.getDate(); // Returns the date
  const month = date.getMonth() + mthAdjust; // Returns the month (adjusted based on type - string or object)
  const year = date.getFullYear(); // Returns the year
  return `${month}/${day}/${year}`;
}

Mark Task as Complete / Incomplete

Using the helper function (getId) the array object is retrieved. It is then updated and returned to local storage.

Line 15 The object id is retrieved.

Line 21 The object id is updated.

// Mark as Complete / Incomplete
function toggleComplete(e) {
  let isComplete;

  if (e.checked) {
    isComplete = true;
  } else {
    isComplete = false;
  }

  // Get Tasks
  let tasks = getLocalStorage();

  // Task Id
  let taskId = getId(e);

  // Find where id matches Task ID
  let task = tasks.find((t) => t.id === taskId);

  // Update object element
  task.complete = isComplete;

  // Set Array
  setLocalStorage(tasks);
  displayData(getLocalStorage());
}        
// Helper function
function getId(e) {
  return e.parentElement.parentElement.children[1].innerText;
}        

Delete Tasks

Similar to Mark Task as Complete, the getId was used to retrieve the task selected.

Line 12 The array filter method is used to retrieve all tasks, excluding the selected task. These tasks are then returned to the array in local storage.

// Delete Tasks
function deleteTask(e) {
  console.log('Delete me!');

  // Get Tasks
  let tasks = getLocalStorage();

  // Task Id
  let taskId = getId(e);

  // Find where id matches Task ID
  let tasksfiltered = tasks.filter((t) => t.id !== taskId);

  // Set Array
  setLocalStorage(tasksfiltered);
  displayData(getLocalStorage());
}                          

Display Data

Templates are used to pull the data and dynamically populate the HTML. This technique is particularly powerful as it keeps the HTML out of the Javascript. In addition, a helper function (formatDate) is used for date clean-up

Lines 3 and 4 Identifies the template and the code destination.

Line 10 In the for loop a copy of the template is populated with data then appended to the target destination.

// Display task data
function displayData(checklistArray) {
  const myTemplate = document.getElementById('Data-Template');
  const resultsBody = document.getElementById('resultsBody');

  // clear table first
  resultsBody.innerHTML = '';

  // Number format reference https://www.w3schools.com/jsref/jsref_tolocalestring_number.asp
  for (let i = 0; i < checklistArray.length; i++) {
    const dataRow = document.importNode(myTemplate.content, true);

    // Checkbox
    let isChecked = checklistArray[i].complete;
    let chkValue = isChecked ? 'checked' : '';
    let checkbox = ``;

    dataRow.getElementById('complete').innerHTML = checkbox;

    dataRow.getElementById('id').textContent = checklistArray[i].id;
    dataRow.getElementById('task').textContent = checklistArray[i].task;
    dataRow.getElementById('createdDate').textContent = formatDate(
      checklistArray[i].createdDate
    );
    dataRow.getElementById('dueDate').textContent = formatDate(
      checklistArray[i].dueDate
    );
    // dataRow.getElementById('controls').textContent = checklistArray[i].controls;

    resultsBody.appendChild(dataRow);
  }
}
// formatDate
function formatDate(strDate) {
  const date = new Date(strDate);
  const day = date.getDate(); // Returns the date
  const month = date.getMonth(); // Returns the month
  const year = date.getFullYear(); // Returns the year
  return `${month}/${day}/${year}`;
}