Congratulations on reaching the final lesson! You've learned 61 concepts across variables, functions, arrays, objects, DOM manipulation, async operations, OOP, and more. Now it's time to bring everything together. We'll build a complete Task Manager application that integrates multiple JavaScript concepts into a real-world project. This isn't just a todo list—it's a comprehensive application demonstrating professional development practices. Let's build something amazing!
Project Overview: Task Manager Pro
Features We'll Implement:
- ✓ Create, read, update, delete tasks (CRUD)
- ✓ Mark tasks as complete/incomplete
- ✓ Filter tasks by status (all, active, completed)
- ✓ Search tasks by text
- ✓ Sort tasks by date or priority
- ✓ Task categories with color coding
- ✓ Due dates with visual indicators
- ✓ LocalStorage persistence
- ✓ Statistics dashboard
- ✓ Input validation and error handling
- ✓ Responsive design
JavaScript Concepts Integrated:
- • Variables, arrays, objects
- • Functions and arrow functions
- • Array methods (map, filter, reduce, sort)
- • Object destructuring
- • DOM manipulation and events
- • Classes and OOP
- • LocalStorage API
- • JSON parse/stringify
- • Template literals
- • Error handling
- • Modern ES6+ features
Step 1: HTML Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Manager Pro</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<header>
<h1>📋 Task Manager Pro</h1>
<div class="stats">
<div class="stat">
<span class="stat-value" id="totalTasks">0</span>
<span class="stat-label">Total</span>
</div>
<div class="stat">
<span class="stat-value" id="activeTasks">0</span>
<span class="stat-label">Active</span>
</div>
<div class="stat">
<span class="stat-value" id="completedTasks">0</span>
<span class="stat-label">Completed</span>
</div>
</div>
</header>
<div class="task-input-section">
<form id="taskForm">
<input
type="text"
id="taskInput"
placeholder="What needs to be done?"
required
>
<select id="categoryInput">
<option value="personal">Personal</option>
<option value="work">Work</option>
<option value="shopping">Shopping</option>
<option value="health">Health</option>
</select>
<input
type="date"
id="dueDateInput"
>
<select id="priorityInput">
<option value="low">Low</option>
<option value="medium" selected>Medium</option>
<option value="high">High</option>
</select>
<button type="submit">Add Task</button>
</form>
</div>
<div class="controls">
<div class="search-box">
<input
type="text"
id="searchInput"
placeholder="🔍 Search tasks..."
>
</div>
<div class="filters">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="active">Active</button>
<button class="filter-btn" data-filter="completed">Completed</button>
</div>
<div class="sort">
<select id="sortSelect">
<option value="date">Sort by Date</option>
<option value="priority">Sort by Priority</option>
<option value="name">Sort by Name</option>
</select>
</div>
</div>
<div class="tasks-container">
<ul id="taskList" class="task-list">
<!-- Tasks will be inserted here dynamically -->
</ul>
<div id="emptyState" class="empty-state">
<p>🎉 No tasks yet. Add one above to get started!</p>
</div>
</div>
<div class="actions">
<button id="clearCompleted">Clear Completed</button>
<button id="clearAll">Clear All</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>Step 2: CSS Styling (Basic)
/* Basic styling - you can expand this */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 10px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
padding: 30px;
}
header {
text-align: center;
margin-bottom: 30px;
}
h1 {
color: #333;
margin-bottom: 20px;
}
.stats {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 20px;
}
.stat {
display: flex;
flex-direction: column;
align-items: center;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #667eea;
}
.stat-label {
font-size: 12px;
color: #666;
text-transform: uppercase;
}
.task-input-section form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
#taskInput {
flex: 1;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
select, button {
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 14px;
cursor: pointer;
}
button[type="submit"] {
background: #667eea;
color: white;
border: none;
font-weight: bold;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.search-box input {
padding: 10px;
border: 2px solid #ddd;
border-radius: 5px;
width: 200px;
}
.filters {
display: flex;
gap: 5px;
}
.filter-btn {
padding: 8px 16px;
background: white;
border: 2px solid #ddd;
border-radius: 5px;
cursor: pointer;
}
.filter-btn.active {
background: #667eea;
color: white;
border-color: #667eea;
}
.task-list {
list-style: none;
}
.task-item {
display: flex;
align-items: center;
gap: 10px;
padding: 15px;
background: #f9f9f9;
border-radius: 5px;
margin-bottom: 10px;
border-left: 4px solid #667eea;
}
.task-item.completed {
opacity: 0.6;
}
.task-item.completed .task-text {
text-decoration: line-through;
}
.task-checkbox {
width: 20px;
height: 20px;
cursor: pointer;
}
.task-content {
flex: 1;
}
.task-text {
font-size: 16px;
color: #333;
}
.task-meta {
display: flex;
gap: 10px;
margin-top: 5px;
font-size: 12px;
color: #666;
}
.task-category {
padding: 2px 8px;
border-radius: 3px;
background: #e0e7ff;
color: #667eea;
}
.task-priority-high {
border-left-color: #ef4444;
}
.task-priority-medium {
border-left-color: #f59e0b;
}
.task-priority-low {
border-left-color: #10b981;
}
.task-actions {
display: flex;
gap: 5px;
}
.btn-edit, .btn-delete {
padding: 5px 10px;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
.btn-edit {
background: #3b82f6;
color: white;
}
.btn-delete {
background: #ef4444;
color: white;
}
.empty-state {
text-align: center;
padding: 40px;
color: #666;
display: none;
}
.empty-state.show {
display: block;
}
.actions {
display: flex;
gap: 10px;
margin-top: 20px;
justify-content: center;
}
.actions button {
background: #ef4444;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}Step 3: JavaScript Implementation
Task Class and Storage Manager
// Task Class - OOP
class Task {
constructor(text, category = 'personal', dueDate = null, priority = 'medium') {
this.id = Date.now() + Math.random(); // Unique ID
this.text = text;
this.category = category;
this.dueDate = dueDate;
this.priority = priority;
this.completed = false;
this.createdAt = new Date();
}
toggle() {
this.completed = !this.completed;
}
update(data) {
Object.assign(this, data);
}
isOverdue() {
if (!this.dueDate || this.completed) return false;
return new Date(this.dueDate) < new Date();
}
}
// Storage Manager - LocalStorage with error handling
class StorageManager {
constructor(key = 'tasks') {
this.key = key;
}
save(tasks) {
try {
localStorage.setItem(this.key, JSON.stringify(tasks));
return true;
} catch (error) {
console.error('Failed to save tasks:', error);
return false;
}
}
load() {
try {
const data = localStorage.getItem(this.key);
if (!data) return [];
const tasks = JSON.parse(data);
// Convert plain objects back to Task instances
return tasks.map(t => {
const task = new Task(t.text, t.category, t.dueDate, t.priority);
task.id = t.id;
task.completed = t.completed;
task.createdAt = new Date(t.createdAt);
return task;
});
} catch (error) {
console.error('Failed to load tasks:', error);
return [];
}
}
clear() {
localStorage.removeItem(this.key);
}
}Main Application Class
// Main Application Class
class TaskManager {
constructor() {
this.tasks = [];
this.storage = new StorageManager();
this.currentFilter = 'all';
this.currentSort = 'date';
this.searchTerm = '';
// DOM elements
this.taskForm = document.getElementById('taskForm');
this.taskInput = document.getElementById('taskInput');
this.categoryInput = document.getElementById('categoryInput');
this.dueDateInput = document.getElementById('dueDateInput');
this.priorityInput = document.getElementById('priorityInput');
this.taskList = document.getElementById('taskList');
this.searchInput = document.getElementById('searchInput');
this.sortSelect = document.getElementById('sortSelect');
this.emptyState = document.getElementById('emptyState');
this.init();
}
init() {
// Load tasks from storage
this.tasks = this.storage.load();
// Setup event listeners
this.setupEventListeners();
// Initial render
this.render();
}
setupEventListeners() {
// Form submission
this.taskForm.addEventListener('submit', (e) => {
e.preventDefault();
this.addTask();
});
// Search
this.searchInput.addEventListener('input', (e) => {
this.searchTerm = e.target.value.toLowerCase();
this.render();
});
// Filter buttons
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
document.querySelectorAll('.filter-btn').forEach(b =>
b.classList.remove('active')
);
e.target.classList.add('active');
this.currentFilter = e.target.dataset.filter;
this.render();
});
});
// Sort
this.sortSelect.addEventListener('change', (e) => {
this.currentSort = e.target.value;
this.render();
});
// Clear buttons
document.getElementById('clearCompleted').addEventListener('click', () => {
this.clearCompleted();
});
document.getElementById('clearAll').addEventListener('click', () => {
if (confirm('Are you sure you want to delete all tasks?')) {
this.clearAll();
}
});
}
addTask() {
const text = this.taskInput.value.trim();
if (!text) {
alert('Please enter a task');
return;
}
const task = new Task(
text,
this.categoryInput.value,
this.dueDateInput.value || null,
this.priorityInput.value
);
this.tasks.push(task);
this.saveTasks();
this.render();
// Reset form
this.taskForm.reset();
this.taskInput.focus();
}
deleteTask(id) {
this.tasks = this.tasks.filter(task => task.id !== id);
this.saveTasks();
this.render();
}
toggleTask(id) {
const task = this.tasks.find(t => t.id === id);
if (task) {
task.toggle();
this.saveTasks();
this.render();
}
}
editTask(id) {
const task = this.tasks.find(t => t.id === id);
if (!task) return;
const newText = prompt('Edit task:', task.text);
if (newText && newText.trim()) {
task.text = newText.trim();
this.saveTasks();
this.render();
}
}
clearCompleted() {
this.tasks = this.tasks.filter(task => !task.completed);
this.saveTasks();
this.render();
}
clearAll() {
this.tasks = [];
this.saveTasks();
this.render();
}
saveTasks() {
this.storage.save(this.tasks);
}
getFilteredTasks() {
let filtered = this.tasks;
// Apply filter
if (this.currentFilter === 'active') {
filtered = filtered.filter(t => !t.completed);
} else if (this.currentFilter === 'completed') {
filtered = filtered.filter(t => t.completed);
}
// Apply search
if (this.searchTerm) {
filtered = filtered.filter(t =>
t.text.toLowerCase().includes(this.searchTerm)
);
}
// Apply sort
filtered = [...filtered].sort((a, b) => {
if (this.currentSort === 'date') {
return b.createdAt - a.createdAt;
} else if (this.currentSort === 'priority') {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return priorityOrder[b.priority] - priorityOrder[a.priority];
} else if (this.currentSort === 'name') {
return a.text.localeCompare(b.text);
}
return 0;
});
return filtered;
}
render() {
const filtered = this.getFilteredTasks();
// Update statistics
this.updateStats();
// Show/hide empty state
if (filtered.length === 0) {
this.taskList.style.display = 'none';
this.emptyState.classList.add('show');
} else {
this.taskList.style.display = 'block';
this.emptyState.classList.remove('show');
}
// Render tasks
this.taskList.innerHTML = filtered.map(task =>
this.createTaskElement(task)
).join('');
// Add event listeners to task elements
this.attachTaskListeners();
}
createTaskElement(task) {
const dueDateText = task.dueDate
? new Date(task.dueDate).toLocaleDateString()
: 'No due date';
const overdueClass = task.isOverdue() ? 'overdue' : '';
return `
<li class="task-item task-priority-${task.priority} ${task.completed ? 'completed' : ''} ${overdueClass}" data-id="${task.id}">
<input
type="checkbox"
class="task-checkbox"
${task.completed ? 'checked' : ''}
>
<div class="task-content">
<div class="task-text">${task.text}</div>
<div class="task-meta">
<span class="task-category">${task.category}</span>
<span class="task-due-date">${dueDateText}</span>
<span class="task-priority">${task.priority} priority</span>
</div>
</div>
<div class="task-actions">
<button class="btn-edit">Edit</button>
<button class="btn-delete">Delete</button>
</div>
</li>
`;
}
attachTaskListeners() {
// Checkbox listeners
document.querySelectorAll('.task-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', (e) => {
const taskItem = e.target.closest('.task-item');
const id = parseFloat(taskItem.dataset.id);
this.toggleTask(id);
});
});
// Edit button listeners
document.querySelectorAll('.btn-edit').forEach(btn => {
btn.addEventListener('click', (e) => {
const taskItem = e.target.closest('.task-item');
const id = parseFloat(taskItem.dataset.id);
this.editTask(id);
});
});
// Delete button listeners
document.querySelectorAll('.btn-delete').forEach(btn => {
btn.addEventListener('click', (e) => {
const taskItem = e.target.closest('.task-item');
const id = parseFloat(taskItem.dataset.id);
this.deleteTask(id);
});
});
}
updateStats() {
const total = this.tasks.length;
const completed = this.tasks.filter(t => t.completed).length;
const active = total - completed;
document.getElementById('totalTasks').textContent = total;
document.getElementById('activeTasks').textContent = active;
document.getElementById('completedTasks').textContent = completed;
}
}
// Initialize app when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
const app = new TaskManager();
// Make app available globally for debugging
window.app = app;
console.log('✅ Task Manager Pro initialized');
});Key Features Explained
1. Object-Oriented Design
// Using classes for organization
class Task {
// Encapsulates task data and behavior
constructor(text, category, dueDate, priority) { }
toggle() { }
update(data) { }
isOverdue() { }
}
class TaskManager {
// Manages all tasks and UI
constructor() { }
addTask() { }
deleteTask(id) { }
render() { }
}
class StorageManager {
// Handles localStorage operations
save(tasks) { }
load() { }
}
// Benefits:
// - Separation of concerns
// - Reusable code
// - Easy to test
// - Clear structure2. Data Persistence
// Save to localStorage
saveTasks() {
this.storage.save(this.tasks);
}
// Load from localStorage
this.tasks = this.storage.load();
// Error handling
save(tasks) {
try {
localStorage.setItem(this.key, JSON.stringify(tasks));
return true;
} catch (error) {
console.error('Failed to save:', error);
return false;
}
}
// Convert to/from JSON
JSON.stringify(tasks) // Save
JSON.parse(data) // Load3. Array Methods in Action
// Filter tasks
const active = this.tasks.filter(t => !t.completed);
const completed = this.tasks.filter(t => t.completed);
// Search tasks
const results = tasks.filter(t =>
t.text.toLowerCase().includes(searchTerm)
);
// Sort tasks
tasks.sort((a, b) => {
if (this.currentSort === 'priority') {
const order = { high: 3, medium: 2, low: 1 };
return order[b.priority] - order[a.priority];
}
return 0;
});
// Map to HTML
const html = tasks.map(task =>
this.createTaskElement(task)
).join('');
// Delete task
this.tasks = this.tasks.filter(task => task.id !== id);
// Count completed
const completed = this.tasks.filter(t => t.completed).length;4. Event Handling
// Form submission
this.taskForm.addEventListener('submit', (e) => {
e.preventDefault();
this.addTask();
});
// Input events
this.searchInput.addEventListener('input', (e) => {
this.searchTerm = e.target.value;
this.render();
});
// Delegation for dynamic elements
document.querySelectorAll('.btn-delete').forEach(btn => {
btn.addEventListener('click', (e) => {
const id = e.target.closest('.task-item').dataset.id;
this.deleteTask(id);
});
});
// Multiple filters
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
this.currentFilter = e.target.dataset.filter;
this.render();
});
});5. DOM Manipulation
// Create HTML from data
createTaskElement(task) {
return `
<li class="task-item ${task.completed ? 'completed' : ''}">
<input type="checkbox" ${task.completed ? 'checked' : ''}>
<div>${task.text}</div>
<button class="btn-delete">Delete</button>
</li>
`;
}
// Insert into DOM
this.taskList.innerHTML = tasks.map(t =>
this.createTaskElement(t)
).join('');
// Update stats
document.getElementById('totalTasks').textContent = total;
// Toggle classes
this.emptyState.classList.add('show');
btn.classList.remove('active');
// Show/hide elements
this.taskList.style.display = 'block';Extending the Project
🚀 Enhancement Ideas:
Take the project further:
- Add subtasks: Create nested tasks
- Tags system: Multiple tags per task
- Drag and drop: Reorder tasks
- Export/Import: JSON or CSV export
- Themes: Light/dark mode
- Keyboard shortcuts: Quick actions
- Notifications: Remind about due dates
- Backend sync: Save to server
- Charts: Visualize progress
- PWA: Make it installable
// Example: Add tags feature
class Task {
constructor(text, category, dueDate, priority) {
// ... existing code
this.tags = []; // Add tags array
}
addTag(tag) {
if (!this.tags.includes(tag)) {
this.tags.push(tag);
}
}
removeTag(tag) {
this.tags = this.tags.filter(t => t !== tag);
}
}
// Example: Export to JSON
exportTasks() {
const dataStr = JSON.stringify(this.tasks, null, 2);
const dataBlob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'tasks.json';
link.click();
URL.revokeObjectURL(url);
}
// Example: Import from JSON
importTasks(file) {
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = JSON.parse(e.target.result);
this.tasks = data.map(t => {
const task = new Task(t.text, t.category, t.dueDate, t.priority);
Object.assign(task, t);
return task;
});
this.saveTasks();
this.render();
} catch (error) {
alert('Failed to import tasks');
}
};
reader.readAsText(file);
}What You've Learned
✅ Concepts Mastered in This Project:
- ✓ Classes and object-oriented programming
- ✓ Constructor functions and methods
- ✓ Array methods (map, filter, sort, reduce)
- ✓ Object destructuring and spread operator
- ✓ Template literals for dynamic HTML
- ✓ Event listeners and event delegation
- ✓ DOM manipulation and updates
- ✓ LocalStorage API for persistence
- ✓ JSON stringify and parse
- ✓ Error handling with try-catch
- ✓ Form validation and user input
- ✓ Conditional rendering
- ✓ State management patterns
- ✓ Code organization and structure
- ✓ Debugging and testing strategies
🎉 Congratulations!
You've completed the entire JavaScript tutorial series!
You've gone from JavaScript basics to building a complete, professional application. You've learned:
- 62 comprehensive lessons
- 15 major topics
- Hundreds of code examples
- Real-world projects
- Professional best practices
What's Next?
- Build more projects to practice
- Contribute to open source
- Learn a framework (React, Vue, Angular)
- Explore Node.js for backend development
- Study advanced topics (TypeScript, testing, performance)
- Join developer communities
- Never stop learning!
🚀 Keep Learning!
JavaScript is constantly evolving. Stay curious, keep building, and remember: every expert was once a beginner. You've taken the first major step—now keep going!
Check out Falytom's other tutorials, join our community, and continue your development journey. We're here to support you!