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)