Project folder structure
App component
import React from "react"; import Todo from "./components/Todo.component"; const App = () => { return <Todo />; }; export default App;
Todo Component
import { useState } from "react"; import "../styles/todo.css"; import TaskItem from "./TaskItem.component"; let taskId = 1; const Todo = () => { const [inputText, setInputText] = useState(""); const [tasks, setTasks] = useState([]); // function to update tasks state const updateTasks = (updatedTasks) => setTasks([...updatedTasks]); // function to handle addition of new tasks const handleAddTaskButtonClicked = (e) => { e.preventDefault(); if (inputText.trim().length === 0) { return; // no need to add new tasks } taskId += 1; const newTask = { id: taskId, desc: inputText, status: { complete: false, }, }; // update state values updateTasks([...tasks, newTask]); setInputText(""); }; // control input element with component state const handleInputChange = (e) => { e.preventDefault(); setInputText(() => e.target.value); }; // add new task on enter key clicked const handleInputKeyDown = (e) => { const keycode = e.keyCode; // check is key pressed is enter key if (keycode === 13) { handleAddTaskButtonClicked(e); } }; return ( <div className="todo_wrapper"> <h1 className="todo_header">TODO LIST</h1> <div className="todo_input_wrapper"> <input className="todo_input_element" type="text" placeholder="What needs to be done?" value={inputText} onChange={handleInputChange} onKeyDown={handleInputKeyDown} /> <button className="add_btn" onClick={handleAddTaskButtonClicked}> ADD </button> </div> <div className="tasks_wrapper"> {tasks.map((taskItem, index) => ( <TaskItem key={index} allTasks={tasks} updateTasks={updateTasks} taskItem={taskItem} /> ))} </div> </div> ); }; export default Todo;
TaskItem component
import React from "react"; import "../styles/todo.css"; const TaskItem = ({ updateTasks, allTasks, taskItem }) => { // function to handle tasks checkbox clicked const handleTaskCheckboxClicked = (e, taskItem) => { let updatedTasks = allTasks.map((elem) => { if (elem.id === taskItem.id) { elem.status.complete = !taskItem.status.complete; // toggle the status } return elem; }); updateTasks(updatedTasks); }; return ( <li className={`task_item ${ taskItem.status.complete === true ? "checked" : "" }`} key={taskItem.id} > <input type="checkbox" className="task_checkbox" onClick={(e) => handleTaskCheckboxClicked(e, taskItem)} /> <p className="">{taskItem.desc}</p> </li> ); }; export default TaskItem;
CSS code
.todo_wrapper { max-width: 600px; padding: 20px; background-color: rgb(55, 68, 95); margin: auto; margin-top: 50px; border-radius: 10px; box-shadow: 8px 13px 23px 0px rgba(0, 0, 0, 0.2); } .todo_header { color: white; text-align: center; } .todo_input_wrapper { display: flex; align-items: stretch; } .todo_input_element { flex-grow: 1; padding: 10px 10px; font-size: 1.1em; font-weight: 500; outline: none; border: none; border-radius: 5px 0 0 5px; } .add_btn { border: none; outline: none; padding: 0px 20px; font-size: 1.1em; font-weight: 700; background-color: lightgray; cursor: pointer; border-radius: 0 5px 5px 0; } .tasks_wrapper { padding: 20px 0; display: flex; flex-direction: column; gap: 10px; } .task_item { display: flex; gap: 10px; align-items: center; list-style-type: none; font-weight: 600; border-radius: 5px; background-color: lightgreen; padding: 10px 15px; } .task_item:hover { background-color: lime; } .task_item p { flex-grow: 1; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .task_checkbox { position: relative; visibility: none; cursor: pointer; margin: 0; } .task_checkbox::before { content: ""; font-weight: 800; width: 1.2em; height: 1.2em; background-color: white; border: 2px solid black; position: absolute; top: 0; left: 0; display: flex; align-items: center; justify-content: center; transform: translate(-25%, -25%); } /* styles for task completed */ .task_item.checked { text-decoration: line-through; color: darkslategrey; background-color: lightslategray; } .task_item.checked:hover { background-color: lightgrey; } .task_item.checked .task_checkbox::before { content: "β"; }
Top comments (0)