diff --git a/index.html b/index.html
index 117e48c..0f44ce4 100644
--- a/index.html
+++ b/index.html
@@ -2,9 +2,9 @@
-
Todo App Tutorial
+
)
}
-export default App
+export default App
\ No newline at end of file
diff --git a/src/components/AddTodo.tsx b/src/components/AddTodo.tsx
index 8d21bc2..fed6148 100644
--- a/src/components/AddTodo.tsx
+++ b/src/components/AddTodo.tsx
@@ -1,8 +1,48 @@
+
import React, { useEffect, useRef, useState } from 'react'
import { toast } from 'react-hot-toast'
-import { useTodo } from '../context'
+import { useTodo } from '../context/useTodo'
import { Input } from './Input'
export const AddTodo = () => {
- return
Add To Do
-}
+ const [input, setInput] = useState
('');
+ // const [todos, setTodos] = useState([]);
+ const inputRef = useRef(null);
+ const {addTodo} = useTodo();
+ const handleSubmit=(e:React.FormEvent)=>{
+ e.preventDefault();
+ if(input.trim()!==''){
+ addTodo(input);
+ setInput('');
+ toast.success('Todo added successfully');
+ }else {
+ toast.error('Todo field cannot be empty!');
+ }
+ // setTodos([...todos, input]);
+ }
+ useEffect(()=>{
+ if(inputRef.current){
+ inputRef.current.focus();
+ }
+ },[]);
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Input.tsx b/src/components/Input.tsx
index ad0b3c1..846ecd6 100644
--- a/src/components/Input.tsx
+++ b/src/components/Input.tsx
@@ -3,6 +3,15 @@ import cn from 'classnames'
import React from 'react'
-export const Input = () => {
- return Input
-}
+export const Input = forwardRef>(({className, ...rest}, ref) => {
+ return (
+
+ )
+});
diff --git a/src/components/TodoItem.tsx b/src/components/TodoItem.tsx
index b6e8621..ecf51a3 100644
--- a/src/components/TodoItem.tsx
+++ b/src/components/TodoItem.tsx
@@ -1,6 +1,6 @@
-import type { Todo } from '../context'
import { useEffect, useRef, useState } from 'react'
-import { useTodo } from '../context'
+import { Todo } from '../context/TodoContext'
+import { useTodo } from '../context/useTodo'
import { Input } from './Input'
import { BsCheck2Square } from 'react-icons/bs'
import { TbRefresh } from 'react-icons/tb'
@@ -11,5 +11,119 @@ import cn from 'classnames'
import { motion } from 'framer-motion'
export const TodoItem = (props: { todo: Todo }) => {
- return Todo Item
-}
+ const { todo } = props
+
+ const [editingTodoText, setEditingTodoText] = useState('')
+ const [editingTodoId, setEditingTodoId] = useState(null)
+
+ const { deleteTodo, editTodo, updateTodoStatus } = useTodo()
+
+ const editInputRef = useRef(null)
+
+ useEffect(() => {
+ if (editingTodoId !== null && editInputRef.current) {
+ editInputRef.current.focus()
+ }
+ }, [editingTodoId])
+
+ const handleEdit = (todoId: string, todoText: string) => {
+ setEditingTodoId(todoId)
+ setEditingTodoText(todoText)
+
+ if (editInputRef.current) {
+ editInputRef.current.focus()
+ }
+ }
+
+ const handleUpdate = (todoId: string) => {
+ if (editingTodoText.trim() !== '') {
+ editTodo(todoId, editingTodoText)
+ setEditingTodoId(null)
+ setEditingTodoText('')
+ toast.success('Todo updated successfully!')
+ } else {
+ toast.error('Todo field cannot be empty!')
+ }
+ }
+
+ const handleDelete = (todoId: string) => {
+ deleteTodo(todoId)
+ toast.success('Todo deleted successfully!')
+ }
+
+ const handleStatusUpdate = (todoId: string) => {
+ updateTodoStatus(todoId)
+ toast.success('Todo status updated successfully!')
+ }
+
+ return (
+
+ {editingTodoId === todo.id ? (
+
+ setEditingTodoText(e.target.value)}
+ />
+
+
+ ) : (
+
+
+ {todo.text}
+
+
+
+
+
+
+
+
+
+ )}
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/TodoList.tsx b/src/components/TodoList.tsx
index 582296b..712ee8d 100644
--- a/src/components/TodoList.tsx
+++ b/src/components/TodoList.tsx
@@ -1,7 +1,25 @@
import { TodoItem } from './TodoItem'
import { useTodo } from '../context'
import { SiStarship } from 'react-icons/si'
+import { motion } from 'framer-motion'
export const TodoList = () => {
- return TodoList
+ const {todos} = useTodo();
+ if(!todos.length){
+ return (
+
+
+
+ You have nothing to do!
+
+
+ )
+ }
+ return (
+
+ {[...todos.filter(todo => todo.status === 'undone'), ...todos.filter(todo => todo.status === 'completed')].map(todo => (
+
+ ))}
+
+ )
}
diff --git a/src/context/TodoContext.tsx b/src/context/TodoContext.tsx
index 04776f2..a8488d5 100644
--- a/src/context/TodoContext.tsx
+++ b/src/context/TodoContext.tsx
@@ -7,13 +7,45 @@ export interface Todo {
text: string
status: 'undone' | 'completed'
}
+interface TodoContextProps {
+ todos: Todo[]
+ addTodo: (text: string) => void
+ deleteTodo:(id: string) => void
+ editTodo:(id: string, text: string) => void
+ updateTodoStatus:(id:string)=>void
-export const TodoContext = createContext(undefined)
+}
+export const TodoContext = createContext(
+ undefined,
+)
export const TodoProvider = (props: { children: React.ReactNode }) => {
+ const [todos, setTodos] = useState([])
+ const addTodo = (text: string) => {
+ const newTodo: Todo = {
+ id: nanoid(),
+ text,
+ status: 'undone',
+ }
+ setTodos([...todos, newTodo])
+ }
+ const deleteTodo = (id: string) => {
+ setTodos(todos.filter(todo => todo.id !== id))
+ }
+ const editTodo = (id: string, text: string) => {
+ setTodos(prevTodos=>prevTodos.map(todo=>todo.id===id?{...todo,text}:todo))
+ }
+ const updateTodoStatus = (id: string) => {
+ setTodos(prevTodos=>prevTodos.map(todo=>todo.id===id?{...todo,status:todo.status==='undone'?'completed':'undone'}:todo))
+ }
+ const value: TodoContextProps = {
+ todos,
+ addTodo,
+ deleteTodo,
+ editTodo,
+ updateTodoStatus,
+ }
return (
-
- {props.children}
-
+ {props.children}
)
}
diff --git a/src/context/useTodo.ts b/src/context/useTodo.ts
index dc77667..9bece8d 100644
--- a/src/context/useTodo.ts
+++ b/src/context/useTodo.ts
@@ -2,5 +2,7 @@ import { useContext } from 'react'
import { TodoContext } from './TodoContext'
export const useTodo = () => {
- return
+ const context = useContext(TodoContext)
+ if (!context) throw new Error('useTodo must be used within a TodoProvider')
+ return context
}
diff --git a/src/main.tsx b/src/main.tsx
index a5fb77c..855906c 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -6,6 +6,8 @@ import { TodoProvider } from './context'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
-
+
+
+
,
)