Lesson 8 +10 XP

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:

  1. Adding new tasks with titles and categories.
  2. Toggling tasks as complete or incomplete.
  3. Filtering tasks by status (All, Active, Completed).
  4. 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().