import React, { useState, useEffect, useContext } from 'react'
import TodosContext from '../context';
const TodoForm = () => {
const [todo, setTodo] = useState("");
const {state: {currentTodo={}}, dispatch} = useContext(TodosContext);
useEffect(() => {
if (currentTodo.text){
setTodo(currentTodo.text)
} else {
setTodo("");
}
}, [currentTodo.id])
const handleSubmit = event => {
event.preventDefault();
if (currentTodo.text){
dispatch({type: "UPDATE_TODO", payload: todo})
} else {
dispatch({type:"ADD_TODO", payload:todo});
}
setTodo("");
}
return (
<form onSubmit={handleSubmit} className="flex justify-center p5">
<input type="text" className=" border-black border-solid border-2" onChange={event => setTodo(event.target.value)} value={todo}/>
</form>
)
}
export default TodoForm
import React, { useContext } from "react"; //in order to consume context need to import useContext from React, don't forget!
import TodosContext from "../context"; //the actual data that will be consumed
export default function TodoList() {
const { state, dispatch } = useContext(TodosContext); //destructure from the context
const title =
state.todos.length > 0 ? `${state.todos.length} Todos` : "Nothing to do!";
return (
<div className="container mx-auto max-w-md text-center font-mono">
<h1 className="text-bold">{title}</h1>
<ul className="list-reset text-white p-0">
{state.todos.map(todo => (
<li
key={todo.id}
className="flex items-center bg-orange-dark border-black border-dashed border-2 my-2 py-4"
style={{ backgroundColor: "orange" }}
>
<span
className={`flex-1 ml-12 text-black cursor-pointer ${todo.complete &&
"line-through text-gray-darkest"}`}
onDoubleClick={() =>
dispatch({ type: "TOGGLE_TODO", payload: todo })
}
>
{todo.text}
</span>
<button
onClick={() =>
dispatch({ type: "SET_CURRENT_TODO", payload: todo })
}
>
{" "}
<img
src="https://icon.now.sh/edit/0050c5"
alt="edit icon"
className="h-6"
/>
</button>
<button>
{" "}
<img
src="https://icon.now.sh/delete/8b0000"
alt="delete icon"
className="h-6"
onClick={() => dispatch({ type: "REMOVE_TODO", payload: todo })}
/>
</button>
</li>
))}
</ul>
</div>
);
}
import uuidv4 from 'uuid/v4'
export default function reducer(state, action){
switch(action.type){
case "ADD_TODO" :
if(!action.payload){
return state;
}
if(state.todos.findIndex(t => t.text === action.payload) > -1) {
return state;
}
const newTodo = {
id: uuidv4(),
text: action.payload,
completed: false
}
const addedTodos = [...state.todos, newTodo]
return {
...state,
todos: addedTodos
}
case "SET_CURRENT_TODO" :
return {
...state,
currentTodo: action.payload
}
case "TOGGLE_TODO" :
const toggledTodos = state.todos.map(t =>
t.id === action.payload.id ? {...action.payload, complete: !action.payload.complete} : t)
return {
...state,
todos: toggledTodos
}
case "UPDATE_TODO":
if(!action.payload){
return state;
}
if(state.todos.findIndex(t => t.text === action.payload) > -1) {
return state;
}
const updatedTodo = { ...state.currentTodo, text: action.payload }
const updatedTodoIndex = state.todos.findIndex(
t => t.id === state.currentTodo.id
)
const updatedTodos = [
...state.todos.slice(0, updatedTodoIndex),
updatedTodo,
...state.todos.slice(updatedTodoIndex + 1)
]
return {
...state,
currentTodo: {},
todos: updatedTodos
}
case "REMOVE_TODO" :
const filteredTodos = state.todos.filter(t => t.id !== action.payload.id);
const isRemovedTodo = state.currentTodo.id === action.payload.id ? {} : state.currentTodo;
return {
...state,
currentTodo: isRemovedTodo,
todos: filteredTodos
}
default:
return state;
}
}