Loading lessons...
Project 1: Interactive Task Tracker
Project 1: Interactive Task Tracker
In this hands-on project, you will build a full-featured Task Tracker Application that combines useState, immutability, and controlled forms to create a real-time todo list.
Project Specifications
Your application will support:
- Adding new tasks with titles and categories.
- Toggling tasks as complete or incomplete.
- Filtering tasks by status (All, Active, Completed).
- Deleting tasks immutably.
import { useState } from 'react';
export default function TaskTracker() {
const [tasks, setTasks] = useState([
{ id: 1, text: "Learn React JSX", category: "Study", completed: true },
{ id: 2, text: "Build Custom Hooks", category: "Coding", completed: false }
]);
const [inputText, setInputText] = useState('');
const [category, setCategory] = useState('General');
const [filter, setFilter] = useState('all');
const addTask = (e) => {
e.preventDefault();
if (!inputText.trim()) return;
const newTask = {
id: Date.now(),
text: inputText,
category,
completed: false
};
setTasks(prev => [...prev, newTask]); // Immutable state update
setInputText('');
};
const toggleTask = (id) => {
setTasks(prev =>
prev.map(t => (t.id === id ? { ...t, completed: !t.completed } : t))
);
};
const deleteTask = (id) => {
setTasks(prev => prev.filter(t => t.id !== id));
};
const filteredTasks = tasks.filter(t => {
if (filter === 'active') return !t.completed;
if (filter === 'completed') return t.completed;
return true;
});
return (
<div className="task-app">
<h2>Interactive Task Tracker</h2>
{/* Controlled Add Form */}
<form onSubmit={addTask}>
<input
type="text"
value={inputText}
onChange={e => setInputText(e.target.value)}
placeholder="New task..."
/>
<select value={category} onChange={e => setCategory(e.target.value)}>
<option value="General">General</option>
<option value="Study">Study</option>
<option value="Coding">Coding</option>
</select>
<button type="submit">Add Task</button>
</form>
{/* Filter Tabs */}
<div className="filters">
<button onClick={() => setFilter('all')}>All</button>
<button onClick={() => setFilter('active')}>Active</button>
<button onClick={() => setFilter('completed')}>Completed</button>
</div>
{/* Task List */}
<ul>
{filteredTasks.map(task => (
<li key={task.id} className={task.completed ? 'done' : ''}>
<span onClick={() => toggleTask(task.id)}>
{task.completed ? '✅' : '⏳'} {task.text} ({task.category})
</span>
<button onClick={() => deleteTask(task.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
Summary & TL;DR
- Practice combining useState, controlled input forms, and immutable state array updates.
- Filter lists dynamically using standard JS
array.filter(). - Toggle completion flags using
array.map().