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.
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