Mark Item as Done¶
We will repeat the same process as for the remove button for our checkbox, it is 99% similar approach.
We add a new function that will dispatch markItemAsDone
action and we pass it to our List.tsx
.
import { useDispatch, useSelector } from "react-redux";
import ListHeader from "../components/ListHeader";
import List from "../components/List";
import { addItem, markItemAsDone, removeItem } from "../store/actions/todo";
import { useState } from "react";
import { RootState } from "../store/reducers";
function App() {
const dispatch = useDispatch();
const [title, setTitle] = useState<string>("");
const todo = useSelector((state: RootState) => state.todo);
const addItemToList = () => {
if (!title) return;
dispatch(addItem(title));
};
const removeItemFromList = (item_id: number) => {
dispatch(removeItem(item_id));
};
const toggleItemDone = (item_id: number) => {
dispatch(markItemAsDone(item_id));
};
return (
<div className="flex justify-center items-center h-screen">
<div className="shadow-lg rounded-lg w-[500px]">
<ListHeader
addItemToList={addItemToList}
title={title}
setTitle={setTitle}
/>
<List
list={todo.todo_list}
removeItemFromList={removeItemFromList}
toggleItemDone={toggleItemDone}
/>
</div>
</div>
);
}
export default App;
Again, we will update our List
component interface to accept toggleItemDone
function and call that function whenever checkbox value changes.
Would be also nice to cross the title of todo item when it is marked as done?
Lets do that, it should be easy using Tailwind's predefined class line-through
on the title of the item if todo item is marked as done.
import { Todo } from "../store/reducers/todo";
interface ListInterface {
list: Todo[];
removeItemFromList: Function;
toggleItemDone: Function;
}
function List(props: ListInterface) {
return (
<ul className="p-8 pt-0 divide-y">
{props.list.length > 0 && props.list.map((todo_item: Todo) => (
<li key={todo_item.id} className="flex items-center p-2">
<input
onChange={() => props.toggleItemDone(todo_item.id)}
type="checkbox"
className="h-4 w-4 mr-2 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"
checked={todo_item.is_done}
/>
<p className={"w-full" + (todo_item.is_done ? ' line-through' : '')}>{todo_item.title}</p>
<button
onClick={() => props.removeItemFromList(todo_item.id)}
type="button"
className="w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-2 py-0.5 bg-white text-base font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-1 focus:ring-offset-2 focus:ring-red-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
>
Remove
</button>
</li>
))}
{props.list.length < 1 && (
<p>Your todo list is empty, please add some todo.</p>
)}
</ul>
);
}
export default List;
We should now be able to mark our items as done and it will mark these items as done in the Redux Store.