From 0715531453bf61dfcf6c12fd0b118315b380cd41 Mon Sep 17 00:00:00 2001 From: no2ehi Date: Fri, 27 Jan 2023 13:04:50 +0330 Subject: [PATCH 1/4] add TodoContext with Reducer & provider & custom Hooks --- src/components/TodoContext.jsx | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/components/TodoContext.jsx diff --git a/src/components/TodoContext.jsx b/src/components/TodoContext.jsx new file mode 100644 index 0000000..90e067f --- /dev/null +++ b/src/components/TodoContext.jsx @@ -0,0 +1,64 @@ +import { createContext, useContext, useReducer } from 'react'; +import dayjs from 'dayjs'; + +const TodosContext = createContext(null); +const TodosDispatchContext = createContext(null); + +export const TodoProvider = ({ children }) => { + const [todos, dispatch] = useReducer(TodoReducer, initialTodos); + + return( + + + {children} + + + ) +} + +const TodoReducer = (state, action) => { + switch(action.type) { + case 'added_todo': { + + } + case 'changed_todo': { + + } + case 'deleted_todo': { + + } + default: { + throw Error('Unknown action: ' + action.type); + } + } + +} + +export const useTodos = () => { + return useContext(TodosContext); +} + +export const useTodosDispatch = () => { + return useContext(TodosDispatchContext); +} + +const initialTodos =[ + { + _id: 1, + title: 'Read boyd language book', + status: false, + deadline: dayjs('2020-09-18T17:11:54'), + }, + { + _id: 2, + title: 'Do My Home Work', + status: true, + deadline: dayjs('2012-02-18T10:16:04'), + }, + { + _id: 3, + title: 'create mini project react', + status: false, + deadline: dayjs('2018-08-18T21:11:54'), + }, +] \ No newline at end of file From e4d50d017c8f3ea062bd9a4805e9c9b633e44a94 Mon Sep 17 00:00:00 2001 From: no2ehi Date: Fri, 27 Jan 2023 16:38:39 +0330 Subject: [PATCH 2/4] add, edit, delete with context and reducer react --- src/App.js | 109 ++---------------------------- src/components/DialogTodoItem.jsx | 27 +++++--- src/components/Header.jsx | 13 +++- src/components/TodoContext.jsx | 76 ++++++++++++++------- src/components/TodoItem.jsx | 29 +++++--- src/components/Todos.jsx | 12 ++-- 6 files changed, 113 insertions(+), 153 deletions(-) diff --git a/src/App.js b/src/App.js index 6dcaf9b..060bcd0 100644 --- a/src/App.js +++ b/src/App.js @@ -2,115 +2,18 @@ import { useState, useEffect } from 'react'; import './App.css'; import Header from './components/Header'; import Todos from './components/Todos'; -import dayjs from 'dayjs'; +import { TodoProvider, useTodosDispatch, useTodos } from './components/TodoContext'; function App() { - const todoData = [ - { - _id: 1, - title: 'Read boyd language book', - status: false, - deadline: dayjs('2020-09-18T17:11:54'), - }, - { - _id: 2, - title: 'Do My Home Work', - status: true, - deadline: dayjs('2012-02-18T10:16:04'), - }, - { - _id: 3, - title: 'create mini project react', - status: false, - deadline: dayjs('2018-08-18T21:11:54'), - }, - ] - - const [listTasks, setListTasks] = useState(todoData); - const [showListTasks, setShowListTasks] = useState([]); - const [modeSort, setModeSort] = useState('All'); - - const handleSubmit = (task) => { - setListTasks([ - ...listTasks, - { - ...task, - } - ]); - } - - const handleDelete = (_id) => { - setListTasks( - listTasks.filter( t => t._id !== _id) - ) - - } - - const handleCheck = (task) => { - setListTasks( - listTasks.map( t => { - if (t._id === task._id) { - let checkedTask = { - ...task, - status: !task.status, - } - return checkedTask; - } else { - return t; - } - }) - ); - } - - const handleEdit = (task) => { - setListTasks( - listTasks.map( t => { - if ( t._id === task._id) { - return task; - } else { - return t; - } - }) - ) - } - - const handleSortList = (mode) => { - setModeSort(mode); - } - - useEffect(() => { - if( modeSort === 'All') { - setShowListTasks( - listTasks - ) - } else if ( modeSort === 'Incomplete') { - let sortedListTasks = listTasks.filter( t => !t.status ); - setShowListTasks( - sortedListTasks - ) - } else { - let sortedListTasks = listTasks.filter( t => t.status ); - setShowListTasks( - sortedListTasks - ) - } - },[listTasks, modeSort]) - - return ( -
+ +

ToDo List

-
- +
+
+
); } diff --git a/src/components/DialogTodoItem.jsx b/src/components/DialogTodoItem.jsx index 1cb8341..b005262 100644 --- a/src/components/DialogTodoItem.jsx +++ b/src/components/DialogTodoItem.jsx @@ -11,18 +11,20 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; import { v4 as uuid } from 'uuid'; +import { useTodosDispatch } from './TodoContext'; -const DialogTodoItem = ({ mode, open, setOpen, handleSubmit, taskEdited }) => { +const DialogTodoItem = ({ mode, open, setOpen, taskEdited }) => { let id = uuid(); - + const [dateOpen, setDateOpen] = useState(false); const [task, setTask] = useState({ _id: id, title: '', status: false, deadline: dayjs('2018-08-18T21:11:54'), }); - const [dateOpen, setDateOpen] = useState(false); + + const dispatch = useTodosDispatch(); const handleChangeTask = (e) => { if (mode === 'edit') { @@ -54,14 +56,19 @@ const DialogTodoItem = ({ mode, open, setOpen, handleSubmit, taskEdited }) => { }; const submitHandler = () => { - handleSubmit(task) + if ( mode ==='add') { + dispatch({ + type: 'added_todo', + task + }) + } else { + dispatch({ + type: 'changed_todo', + task + }) + } setOpen(false); - setTask({ - _id: "", - title: "", - status: false, - deadline: dayjs('2018-08-18T21:11:54') - }); + setTask(null); } useEffect(() => { diff --git a/src/components/Header.jsx b/src/components/Header.jsx index 3c28b3f..a0dea43 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -1,21 +1,28 @@ import { useState } from 'react'; import DialogTodoItem from './DialogTodoItem'; +import { useTodosDispatch } from './TodoContext'; -const Header = ({ handleSubmit, sortHandler }) => { +const Header = () => { const [open, setOpen] = useState(false); + const dispatch = useTodosDispatch(); return(
- dispatch({ + type: 'sorted_todo', + mode: e.target.value + }) + } className="bg-gray-300 rounded-lg font-medium text-gray-600 px-4 py-2" > - { open && } + { open && }
) diff --git a/src/components/TodoContext.jsx b/src/components/TodoContext.jsx index 90e067f..7391579 100644 --- a/src/components/TodoContext.jsx +++ b/src/components/TodoContext.jsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useReducer } from 'react'; +import { createContext, useContext, useReducer, useState } from 'react'; import dayjs from 'dayjs'; const TodosContext = createContext(null); @@ -16,16 +16,46 @@ export const TodoProvider = ({ children }) => { ) } -const TodoReducer = (state, action) => { +const TodoReducer = (todos, action) => { + // const [copyTodos, setCopyTodos] = useState(todos); + switch(action.type) { case 'added_todo': { - + return [ + ...todos, + action.task + ] } case 'changed_todo': { - + // console.log(action.task); + return todos.map( t => { + if (t._id === action.task._id) { + return { + ...action.task, + status: action.status + } + } else { + return t; + }}); + } + case 'sorted_todo': { + // console.log('todos: ', ...todos); + if( action.mode === 'All') { + // todos = copyTodos; + return todos; + } else if ( action.mode === 'Incomplete') { + let sortedListTasks = todos.filter( t => !t.status ); + // setCopyTodos(todos); + return sortedListTasks; + } else { + let sortedListTasks = todos.filter( t => t.status ); + // setCopyTodos(todos); + return sortedListTasks; + } } case 'deleted_todo': { - + console.log('hi',action._id) + return todos.filter( t => t._id !== action._id) } default: { throw Error('Unknown action: ' + action.type); @@ -43,22 +73,22 @@ export const useTodosDispatch = () => { } const initialTodos =[ - { - _id: 1, - title: 'Read boyd language book', - status: false, - deadline: dayjs('2020-09-18T17:11:54'), - }, - { - _id: 2, - title: 'Do My Home Work', - status: true, - deadline: dayjs('2012-02-18T10:16:04'), - }, - { - _id: 3, - title: 'create mini project react', - status: false, - deadline: dayjs('2018-08-18T21:11:54'), - }, + { + _id: 1, + title: 'Read boyd language book', + status: false, + deadline: dayjs('2020-09-18T17:11:54'), + }, + { + _id: 2, + title: 'Do My Home Work', + status: true, + deadline: dayjs('2012-02-18T10:16:04'), + }, + { + _id: 3, + title: 'create mini project react', + status: false, + deadline: dayjs('2018-08-18T21:11:54'), + }, ] \ No newline at end of file diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx index 5cad033..9af2b9d 100644 --- a/src/components/TodoItem.jsx +++ b/src/components/TodoItem.jsx @@ -3,31 +3,44 @@ import CheckBoxIcon from '@mui/icons-material/CheckBox'; import DeleteIcon from '@mui/icons-material/Delete'; import EditIcon from '@mui/icons-material/Edit'; import DialogTodoItem from './DialogTodoItem'; +import { useTodosDispatch } from './TodoContext'; -const Task = ( { task, deleteHandler, checkHandler, editeHandler } ) => { +const Task = ({ todo }) => { const [openEdit, setOpenEdit] = useState(false); + const dispatch = useTodosDispatch(); return(
-
- {task.title} + className={`text-gray-700 font-medium ${todo.status && 'line-through'} `} > + {todo.title} - {task.deadline.$d.toLocaleString()} + {todo.status}
-
{ openEdit && - + }
) diff --git a/src/components/Todos.jsx b/src/components/Todos.jsx index c8ec8b4..9b04f92 100644 --- a/src/components/Todos.jsx +++ b/src/components/Todos.jsx @@ -1,15 +1,15 @@ import Task from './TodoItem'; +import { useTodos } from './TodoContext'; -const Tasks = ({ tasks, deleteHandler, checkHandler, editeHandler }) => { +const Tasks = () => { + + const todos = useTodos(); return(
- { tasks.length > 0 ? tasks.map( (task, i) => ( + { todos.length > 0 ? todos.map( (todo, i) => ( )) : (
From 84988f832a81a9134594837798f7cb7be423cfff Mon Sep 17 00:00:00 2001 From: no2ehi Date: Sat, 28 Jan 2023 08:27:02 +0330 Subject: [PATCH 3/4] add, edit, delete with context and reducer react --- src/App.js | 2 +- src/components/DialogTodoItem.jsx | 8 ++- src/components/Header.jsx | 2 +- src/components/TodoContext.jsx | 99 ++++++++++++++++++++----------- src/components/TodoItem.jsx | 7 ++- src/components/Todos.jsx | 31 ++++++++-- 6 files changed, 101 insertions(+), 48 deletions(-) diff --git a/src/App.js b/src/App.js index 060bcd0..6222eff 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'; import './App.css'; import Header from './components/Header'; import Todos from './components/Todos'; -import { TodoProvider, useTodosDispatch, useTodos } from './components/TodoContext'; +import { TodoProvider } from './components/TodoContext'; function App() { diff --git a/src/components/DialogTodoItem.jsx b/src/components/DialogTodoItem.jsx index b005262..ff261c3 100644 --- a/src/components/DialogTodoItem.jsx +++ b/src/components/DialogTodoItem.jsx @@ -57,14 +57,15 @@ const DialogTodoItem = ({ mode, open, setOpen, taskEdited }) => { const submitHandler = () => { if ( mode ==='add') { + console.log('add: ',task) dispatch({ type: 'added_todo', - task + payload: task }) } else { dispatch({ type: 'changed_todo', - task + payload: task }) } setOpen(false); @@ -123,7 +124,8 @@ const DialogTodoItem = ({ mode, open, setOpen, taskEdited }) => { onClose={() => setDateOpen(false)} onChange={handleChangeDateTask} renderInput={(params) => setDateOpen(true)} />} + onClick={() => setDateOpen(true)} + />} /> diff --git a/src/components/Header.jsx b/src/components/Header.jsx index a0dea43..3318962 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -13,7 +13,7 @@ const Header = () => {