Interactive Todo List

Project Overview

Create an advanced todo list application that demonstrates your mastery of arrays and DOM manipulation. This project builds on the basic todo list by adding more sophisticated array operations and dynamic features.

ArraysDOM ManipulationEvent HandlingIntermediate60 minutes

Learning Objectives

  • Master array methods for data management
  • Implement complex filtering and sorting
  • Handle dynamic DOM updates efficiently
  • Practice advanced array transformations
  • Implement data persistence

Project Requirements

1. Task Management

  • Create an array of task objects with properties:
    • id: number (unique identifier)
    • title: string (task description)
    • completed: boolean (task status)
    • priority: string (high, medium, low)
    • dueDate: Date (optional)
    • tags: array (task categories)
  • Display tasks in a structured list
  • Show task details and status indicators

2. Array Operations

  • Filter tasks by status using array filter()
  • Sort tasks by priority and due date using sort()
  • Group tasks by tags using reduce()
  • Search tasks using array methods
  • Batch operations (complete all, delete completed)

3. Advanced Features

  • Implement task categories with tag management
  • Add task priority levels and sorting
  • Create task statistics using array reduce()
  • Add data persistence using localStorage
  • Implement undo/redo functionality

Getting Started

Step 1: Set Up Data Structure

const todoApp = {
  tasks: [
    {
      id: 1,
      title: 'Complete project documentation',
      completed: false,
      priority: 'high',
      dueDate: new Date('2024-03-20'),
      tags: ['work', 'documentation']
    },
    // Add more tasks...
  ],
  filters: {
    status: 'all',
    priority: 'all',
    tags: []
  }
};

Step 2: Implement Core Functions

// Filter tasks
function filterTasks() {
  return todoApp.tasks
    .filter(task => {
      const statusMatch = todoApp.filters.status === 'all' || 
        (todoApp.filters.status === 'completed') === task.completed;
      const priorityMatch = todoApp.filters.priority === 'all' ||
        todoApp.filters.priority === task.priority;
      const tagMatch = todoApp.filters.tags.length === 0 ||
        todoApp.filters.tags.some(tag => task.tags.includes(tag));
      return statusMatch && priorityMatch && tagMatch;
    });
}

// Sort tasks
function sortTasks(tasks) {
  const priorityOrder = { high: 1, medium: 2, low: 3 };
  return [...tasks].sort((a, b) => {
    // Sort by priority first
    const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
    if (priorityDiff !== 0) return priorityDiff;
    // Then by due date
    return a.dueDate - b.dueDate;
  });
}

Step 3: Add Statistics and Persistence

// Calculate statistics
function getStatistics() {
  return todoApp.tasks.reduce((stats, task) => {
    stats.total++;
    if (task.completed) stats.completed++;
    stats.byPriority[task.priority]++;
    task.tags.forEach(tag => {
      stats.byTag[tag] = (stats.byTag[tag] || 0) + 1;
    });
    return stats;
  }, {
    total: 0,
    completed: 0,
    byPriority: { high: 0, medium: 0, low: 0 },
    byTag: {}
  });
}

// Save to localStorage
function saveState() {
  localStorage.setItem('todoApp', 
    JSON.stringify(todoApp)
  );
}

Tips for Success

  • Use immutable array operations to maintain data integrity
  • Implement proper error handling for all operations
  • Use meaningful variable names and add comments
  • Break down complex operations into smaller functions
  • Test edge cases in your filtering and sorting logic

Bonus Challenges

  • Add subtasks using nested arrays
  • Implement task dependencies
  • Add drag-and-drop task reordering
  • Create task analytics dashboard
  • Add task sharing functionality