The Code

                    
                        let tasks = JSON.parse(localStorage.getItem('taskArray')) || [];
                        let editIdNumber = 0;
                        let workingData = tasks;

                        function enableToolTips() {
                            var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
                            var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
                                return new bootstrap.Tooltip(tooltipTriggerEl)
                            })
                        }

                        function createTask() {
                            let taskField = document.getElementById('newTask');
                            let dateField = document.getElementById('newDateDue')
                            let task = taskField.value;
                            let createdDate = new Date().toLocaleDateString();

                            let date = dateField.value == "" ?
                                new Date().toLocaleDateString() :
                                new Date(`${dateField.value} 00:00`).toLocaleDateString();

                            
                            if (task == '') {
                                Swal.fire('Please enter a task');
                            } else {
                                // build task object
                                let taskObject = {
                                    task: task,
                                    id: tasks.length,
                                    taskDate: date,
                                    created: createdDate,
                                    completed: false,
                                    late: false,
                                    buttonCell: `<button class='btn' onclick="markCompleted(this)" data-string="${tasks.length}" data-bs-toggle="tooltip"  title="Mark Completed"><span class="text-primary"><i class="fas fa-check-square"></i></span></button>  
                                    <button class="btn" onclick="editTask(this)" data-string="${tasks.length}" data-bs-toggle="tooltip"  title="Edit Task"><i class="fas fa-edit"></i></button> 
                                    <button class='btn'  onclick="deleteTask(this)" data-string="${tasks.length}" data-bs-toggle="tooltip"  title="Delete Task"><span class="text-danger"><i class="fas fa-trash-alt"></span></i></button>
                                    `
                                }
                                // add to tasks 
                                tasks.push(taskObject);
                                // update localStorage
                                localStorage.setItem('taskArray', JSON.stringify(tasks))
                            }

                            closeModal();
                            display();
                            clearForm('createForm');
                        }

                        function clearTasks() {
                            // set tasks to []
                            tasks = [];
                            // update localStorage
                            localStorage.setItem('taskArray', JSON.stringify(tasks));
                            workingData = tasks;
                            display();
                        }

                        function clearToolTip() {
                            $("div.tooltip").hide();
                            // let ttDiv = document.querySelector('.tooltip')
                            // ttDiv.hide();
                        }

                        function filter(task) {
                            const template = document.getElementById('taskTemplate');
                            const taskBody = document.getElementById('taskBody');
                            let filterHead = document.getElementById('filterData');
                            taskBody.innerHTML = '';

                            // sort tasks by filter
                            if (task == 'all') {
                                // display all
                                filterHead.innerHTML = `All Tasks(${workingData.length})`
                                clearFilter();
                            } else if (task == 'incomplete') {
                                // loop and find completed == false
                                //display
                                workingData = [];

                                for (let i = 0; i < tasks.length; i++) {
                                    if (tasks[i].completed == false) {
                                        workingData.push(tasks[i]);
                                    }
                                }
                                filterHead.innerHTML = `Incomplete Tasks(${workingData.length})`
                                display();

                            } else if (task == 'completed') {
                                // loop and find completed == true
                                // display
                                workingData = [];

                                for (let i = 0; i < tasks.length; i++) {
                                    if (tasks[i].completed == true) {
                                        workingData.push(tasks[i]);
                                    }
                                }
                                filterHead.innerHTML = `Completed Tasks(${workingData.length})`
                                display();

                            } else if (task == 'late') {
                                workingData = [];
                                for (let i = 0; i < tasks.length; i++) {
                                    if (Date.parse(generateModalDueDate(tasks[i].taskDate)) < new Date()) {
                                        workingData.push(tasks[i]);
                                    }
                                }
                                filterHead.innerHTML = `Over Due Tasks(${workingData.length})`
                                display();

                            } else if (task == 'search') {
                                let searchTerm = document.getElementById('searchBar').value;
                                workingData = [];

                                for (let i = 0; i < tasks.length; i++) {
                                    if (tasks[i].task.includes(searchTerm)) {
                                        workingData.push(tasks[i])
                                    }
                                }
                                filterHead.innerHTML = `Search: ${searchTerm} (${workingData.length}) Found`
                                display();

                            }
                        }

                        function clearFilter() {
                            workingData = tasks;
                            display();
                        }

                        function display() {
                            const template = document.getElementById('taskTemplate');
                            const taskBody = document.getElementById('taskBody');
                            // clear screen
                            taskBody.innerHTML = '';
                            // defaults to all
                            for (let i = 0; i < workingData.length; i++) {
                                let taskRow = document.importNode(template.content, true);
                                if (workingData[i].completed) {
                                    taskRow.getElementById('task').innerHTML = `<span class="text-decoration-line-through">${workingData[i].task}</span>`;
                                    taskRow.getElementById('created').innerHTML = `<span class="text-decoration-line-through">${workingData[i].created}</span>`;
                                    taskRow.getElementById('dueDate').innerHTML = `<span class="text-decoration-line-through">${workingData[i].taskDate}</span>`;
                                    taskRow.getElementById('buttons').innerHTML = `<span>${workingData[i].buttonCell}</span>`;
                                } else {

                                    taskRow.getElementById('task').innerHTML = `<span class="text-decoration-none">${workingData[i].task}</span>`;
                                    taskRow.getElementById('created').innerHTML = `<span class="text-decoration-none">${workingData[i].created}</span>`;
                                    taskRow.getElementById('dueDate').innerHTML = `<span class="text-decoration-lnone">${workingData[i].taskDate}</span>`;
                                    taskRow.getElementById('buttons').innerHTML = `<span >${workingData[i].buttonCell}</span>`;
                                }
                                taskBody.appendChild(taskRow);
                            }
                            enableToolTips();
                        }

                        function markCompleted(element) {
                            let elementId = parseInt(element.getAttribute('data-string'))
                            // get this object from button
                            // flip taskCompleted bool
                            if (tasks[elementId].completed == true) {
                                tasks[elementId].completed = false;
                                for (let i = 0; i < workingData.length; i++) {
                                    if (workingData[i].id == elementId) {
                                        workingData[i].compelted = false;
                                    }
                                }
                            } else {
                                tasks[elementId].completed = true;
                                for (let i = 0; i < workingData.length; i++) {
                                    if (workingData[i].id == elementId) {
                                        workingData[i].compelted = true;
                                    }
                                }
                            }

                            localStorage.setItem('taskArray', JSON.stringify(tasks));
                            // change style to strikeout
                            // added to display
                            display();
                            clearToolTip()
                        }

                        function editTask(element) {
                            let elementId = parseInt(element.getAttribute('data-string'))
                            // get this object from button
                            // open edit dialog
                            editIdNumber = elementId;
                            // fill inputs with current data
                            let editTask = document.getElementById('editTask');
                            editTask.value = tasks[elementId].task;
                            let editDateDue = document.getElementById('editDateDue');

                            editDateDue.value = generateModalDueDate(tasks[elementId].taskDate);
                            // editDateDue.value = new Date(tasks[elementId].taskDate).toLocaleDateString();
                            clearToolTip();
                            // if data is changed, change task
                            // property
                            let editModal = new bootstrap.Modal(document.getElementById('editModal'));
                            editModal.show();
                            // update screen
                        }

                        function generateModalDueDate(date) {

                            let dateArray = date.split("/");
                            let newDate = `${dateArray[2]}-`;
                            if (dateArray[0].length == 2) {
                                newDate += `${dateArray[0]}-`;
                            } else {
                                newDate += `0${dateArray[0]}-`
                            }
                            if (dateArray[1].length == 2) {
                                newDate += `${dateArray[1]}`;
                            } else {
                                newDate += `0${dateArray[1]}`
                            }

                            return newDate;
                        }

                        function updateTask() {

                            // get user inputs
                            let taskField = document.getElementById('editTask');
                            let dateField = document.getElementById('editDateDue')
                            let task = taskField.value;
                            let createdDate = new Date().toLocaleDateString();
                            let completed = tasks[editIdNumber].completed;
                            let date = new Date(`${dateField.value} 00:00`).toLocaleDateString();

                            if (task == '') {
                                Swal.fire('Please enter a task');
                            } else {
                                // build task object
                                let taskObject = {
                                    task: task,
                                    id: editIdNumber,
                                    taskDate: date,
                                    created: createdDate,
                                    completed: completed,
                                    buttonCell: `<button class='btn' onclick="markCompleted(this)" data-string="${editIdNumber}"><span class="text-primary"><i class="fas fa-check-square"></i></span></button>  
                                    <button class="btn" onclick="editTask(this)" data-string="${editIdNumber}"><i class="fas fa-edit"></i></button> 
                                    <button class='btn'  onclick="deleteTask(this)" data-string="${editIdNumber}"><span class="text-danger"><i class="fas fa-trash-alt"></span></i></button>
                                    `
                                }
                                // add to tasks 
                                tasks[editIdNumber] = taskObject;
                                // update localStorage
                                localStorage.setItem('taskArray', JSON.stringify(tasks))
                                for (let i = 0; i < workingData.length; i++) {
                                    if (workingData[i].id == taskObject.id) {
                                        workingData[i].task = task;
                                    }
                                }
                            }

                            clearToolTip();

                            closeEditModal();
                            display();
                            clearForm('editForm');

                        }

                        function deleteTask(element) {
                            // get index of this object from button
                            // array.splice(index, 1) to remove
                            let elementId = parseInt(element.getAttribute('data-string'))
                            tasks.splice(elementId, 1);

                            for (let i = 0; i < workingData.length; i++) {
                                if (workingData[i].id == elementId) {
                                    workingData.splice(i, 1);
                                }
                            }


                            // reset task indexes
                            for (let i = elementId; i < tasks.length; i++) {
                                tasks[i].id = i;
                                tasks[i].buttonCell = `<button class="btn"  onclick="markCompleted(this)" data-string="${i}" data-bs-toggle="tooltip"  title="Mark Completed"><span class="text-primary"><i class="fas fa-check-square"></i></span></button>  
                                <button class="btn" onclick="editTask(this)" data-string="${i}" data-bs-toggle="tooltip"  title="Edit Task"><i class="fas fa-edit"></i></button> 
                                <button class="btn" onclick="deleteTask(this)" data-string="${i}" data-bs-toggle="tooltip"  title="Delete Task"><span class="text-danger"><i class="fas fa-trash-alt"></span></i></button>
                                `
                            }

                            clearToolTip();
                            localStorage.setItem('taskArray', JSON.stringify(tasks));
                            display();


                        }

                        function closeModal() {
                            // let modal = new bootstrap.Modal(document.getElementById('exampleModal'), {});
                            // modal.hide();

                            let modalBtn = document.getElementById('closeModalBtn');
                            modalBtn.click();
                        }

                        function closeEditModal() {
                            // let modal = new bootstrap.Modal(document.getElementById('exampleModal'), {});
                            // modal.hide();

                            let modalBtn = document.getElementById('closeEditModalBtn');
                            modalBtn.click();
                        }

                        function formatDate(dateString) {
                            let dateArray = dateString.split("/");
                            if (dateArray[0].length = 1) {
                                let value = dateArray[0];
                                dateArray[0] = `0${value}`;
                            }
                            if (dateArray[1].length = 1) {
                                let value = dateArray[1];
                                dateArray[1] = `0${value}`;
                            }

                            return `${dateArray[2]}-${dateArray[0]}-${dateArray[1]} 00:00`
                        }

                        function clearForm(form) {
                            document.getElementById(form).reset();
                        }

                        function setupEventListeners() {
                            document.getElementById("taskSave").addEventListener("click", createTask);
                            document.getElementById("clearFilter").addEventListener("click", clearFilter);
                            document.getElementById("editSave").addEventListener("click", function (e) {
                                e.preventDefault();
                                updateTask();
                            });


                            document.getElementById("taskClear").addEventListener("click", clearTasks);
                            document.getElementById("menuClearTasks").addEventListener("click", clearTasks);
                            window.onload = filter('all');
                            document.getElementById("newTask").addEventListener('keypress', function (keyPressed) {

                                if (keyPressed.key === "Enter") {
                                    keyPressed.preventDefault();
                                    createTask();

                                }
                            })
                            document.getElementById("newDateDue").addEventListener('keypress', function (keyPressed) {
                                if (keyPressed.key === "Enter") {
                                    keyPressed.preventDefault();
                                    createTask();
                                }
                            });
                            document.getElementById("editTask").addEventListener('keypress', function (keyPressed) {
                                if (keyPressed.key === "Enter") {
                                    keyPressed.preventDefault();
                                    updateTask();
                                }
                            });
                            document.getElementById("editDateDue").addEventListener('keypress', function (keyPressed) {
                                if (keyPressed.key === "Enter") {
                                    keyPressed.preventDefault();
                                    updateTask();
                                }
                            });
                            document.getElementById("searchBtn").addEventListener("click", (e) => {
                                e.preventDefault();
                                filter('search');
                            });
                            document.getElementById("displayAll").addEventListener("click", () => {
                                filter('all');
                            });
                            document.getElementById("filterIncomplete").addEventListener("click", () => {
                                filter('incomplete');
                            });
                            document.getElementById("filterCompleted").addEventListener("click", () => {
                                filter('completed');
                            });
                            document.getElementById("filterLate").addEventListener("click", () => {
                                filter('late');
                            });


                        }
                    
                    

Task Master uses 17 functions to achieve functionality. Rather than go through them all, I'll highlight the ones I think were challenging.

createTask() lets us build a task object based on user input and a predefined object template. Each object holds a task, an id (based on the length of our storage array), the date created, the due date, if its completed, if its late, and a dynamic button group filled with our completion, edit and delete butttons. I assign them a data-string containing the user id so that when I want to edit a specific item, the button knows which item to work with.


clearTasks() simply clears the local storage and redisplays the screen


filter(task) takes in a type of task and filters the display to match. It rebuilds our workingData with a subset of the full local storage.


display() takes our new workingData array and displays it on the screen


markCompleted() swaps the boolean value in our task array. It uses the id number passed to it from the button to know which row to mark. display() handles the actual styling.


updateTask() and deleteTask() both use the same strategy for handling ids and rows.


The other functions are helper functions used for formatting dates, opening/closing modals and setting up event listeners.