Back to all posts

#4 Todo List | 25 React Project


Building form component and App.jsx

//CustomForm.jsx
import { PlusIcon } from "@heroicons/react/24/solid";

function CustomForm() {
  const handleFormSubmit = (e) => {
    e.preventDefault();
    console.log("Form submitted");
  };

  return (
    <form className="todo" onSubmit={handleFormSubmit}>
      <div className="wrapper">
        <input
          type="task"
          id="task"
          className="input"
          required
          autoFocus
          maxLength={60}
          placeholder="Enter task"
        />
        <label htmlFor="task" className="label">
          Enter Task
        </label>
      </div>
      <button className="btn" aria-label="Add Task" type="submit">
        <PlusIcon />
      </button>
    </form>
  );
}

export default CustomForm;
//App.jsx
import "./App.css";
import CustomForm from "./components/CustomForm";
function App() {
  return (
    <div className="container">
      <header>
        <h1>Todo App</h1>
      </header>
      <CustomForm />
    </div>
  );
}

export default App;

Displaying tasks in a list

App.jsx
import { useState } from "react";
import "./App.css";
import CustomForm from "./components/CustomForm";
import TaskList from "./components/TaskList";

function App() {
  const [tasks, setTasks] = useState([]);

  const addTask = (task) => {
    setTasks((prevTask) => [...prevTask, task]);
  };

  return (
    <div className="container">
      <header>
        <h1>Todo App</h1>
      </header>
      <CustomForm addTask={addTask} />
      <TaskList tasks={tasks} />
    </div>
  );
}

export default App;
//CustomForm.jsx
import { useState } from "react";
// librabry imports
import { PlusIcon } from "@heroicons/react/24/solid";

function CustomForm({ addTask }) {
  const [task, setTask] = useState("");
  const handleFormSubmit = (e) => {
    e.preventDefault();
    addTask({
      name: task,
      checked: false,
      id: Date.now(),
    });
    console.log("Form submitted");
    setTask("");
  };

  return (
    <form className="todo" onSubmit={handleFormSubmit}>
      <div className="wrapper">
        <input
          type="task"
          id="task"
          className="input"
          required
          autoFocus
          maxLength={60}
          placeholder="Enter task"
          value={task}
          onChange={(e) => setTask(e.target.value)}
        />
        <label htmlFor="task" className="label">
          Enter Task
        </label>
      </div>
      <button className="btn" aria-label="Add Task" type="submit">
        <PlusIcon />
      </button>
    </form>
  );
}

export default CustomForm;
//TaskList.jsx
import TaskItem from "./TaskItem";
import classes from "./TaskList.module.css";
const TaskList = ({ tasks }) => {
  return (
    <ul className={classes.tasks}>
      {tasks
        .sort((a, b) => b.id - a.id) // To order task on Stack Order
        .map((task) => (
          <TaskItem key={task.id} task={task} />
        ))}
    </ul>
  );
};

export default TaskList;
//TaskItem
import { useState } from "react";
import classes from "./TaskItem.module.css";
import { CheckIcon } from "@heroicons/react/24/outline";
import { PencilSquareIcon } from "@heroicons/react/24/outline";
import { TrashIcon } from "@heroicons/react/24/outline";

function TaskItem({ task }) {
  const [isChecked, setIsChecked] = useState(task.checked);

  const handleCheckboxChange = (e) => {
    setIsChecked(!isChecked);
  };
  return (
    <li className={classes.task}>
      <div className={classes["task-group"]}>
        <input
          type="checkbox"
          className={classes.checkbox}
          onChange={handleCheckboxChange}
          checked={isChecked}
          name={task.name}
          id={task.id}
        />
        <label htmlFor={task.id} className={classes.label}>
          {task.name}
          <p className={classes.checkmark}>
            <CheckIcon strokeWidth={2} width={24} height={24} />
          </p>
        </label>
      </div>
      <div className={classes["task-group"]}>
        <button
          className="btn"
          area-label={`Update ${task.name} Task`}
          // onClick={}
        >
          <PencilSquareIcon width={24} height={24} />
        </button>
        <button
          className={`btn ${classes.delete}`}
          area-label={`Delete ${task.name} Task`}
          // onClick={}
        >
          <TrashIcon width={24} height={24} />
        </button>
      </div>
    </li>
  );
}

export default TaskItem;