@@ -16,6 +16,11 @@ function TodoList() {
16
16
return initialValue
17
17
} )
18
18
19
+ useEffect (
20
+ ( ) => window . localStorage . setItem ( "todos" , JSON . stringify ( todos ) ) ,
21
+ [ todos ]
22
+ )
23
+
19
24
const handleCreateTodo = ( todo : string ) => {
20
25
const oldTodos = [ ...todos ]
21
26
oldTodos . push ( {
@@ -24,15 +29,47 @@ function TodoList() {
24
29
isCompleted : false ,
25
30
} )
26
31
setTodos ( oldTodos )
27
- window . localStorage . setItem ( "todos" , JSON . stringify ( oldTodos ) )
28
32
}
29
33
34
+ const handleDeleteTodo = ( todoId : number ) => {
35
+ let updatedTodos = [ ...todos ]
36
+ let selectedTodoIdx = todos . findIndex ( ( todo ) => todo . id === todoId )
37
+ updatedTodos . splice ( selectedTodoIdx , 1 )
38
+ setTodos ( updatedTodos )
39
+ }
40
+ const handleComplete = ( todoId : number ) => {
41
+ // clone the original array to avoid mutate by reference
42
+ let updatedTodos = [ ...todos ]
43
+ // find the todo based on todo id
44
+ let selectedTodo = todos . find ( ( todo ) => todo . id === todoId )
45
+ // find the todo index based on todo id
46
+ let selectedTodoIdx = todos . findIndex ( ( todo ) => todo . id === todoId )
47
+
48
+ if ( selectedTodo ) {
49
+ updatedTodos [ selectedTodoIdx ] = {
50
+ ...selectedTodo ,
51
+ isCompleted : ! selectedTodo . isCompleted ,
52
+ }
53
+ setTodos ( updatedTodos )
54
+ }
55
+ }
30
56
return (
31
- < div >
57
+ < div className = "bg-white shadow-md w-2/5 p-8 rounded-xl" >
58
+ < h1 className = "text-2xl font-bold" > Todo List</ h1 >
59
+ < hr className = "mt-2" />
32
60
< TodoNew createTodo = { handleCreateTodo } />
33
- < div >
61
+ < div className = "mt-4" >
62
+ You have { todos . filter ( ( it ) => it . isCompleted === false ) . length } pending
63
+ task(s)
64
+ </ div >
65
+ < div className = "mt-4" >
34
66
{ todos . map ( ( it ) => (
35
- < TodoItem key = { it . id } item = { it } />
67
+ < TodoItem
68
+ key = { it . id }
69
+ item = { it }
70
+ deleteTodo = { handleDeleteTodo }
71
+ complete = { handleComplete }
72
+ />
36
73
) ) }
37
74
</ div >
38
75
</ div >
@@ -49,19 +86,84 @@ function TodoNew({ createTodo }: TodoNewProps) {
49
86
setTodo ( "" )
50
87
}
51
88
return (
52
- < form onSubmit = { onSubmit } >
89
+ < form onSubmit = { onSubmit } className = "relative" >
90
+ < span className = "absolute top-5 right-3" >
91
+ < PlusCircle />
92
+ </ span >
53
93
< input
54
94
type = "text"
55
95
placeholder = "Add new task"
56
96
value = { todo }
97
+ className = "bg-blue-50 p-3 rounded-full mt-2 w-full"
57
98
onChange = { ( e ) => setTodo ( e . target . value ) }
58
99
/>
59
100
</ form >
60
101
)
61
102
}
103
+ interface TodoItemProps {
104
+ item : Todo
105
+ deleteTodo : ( id : number ) => void
106
+ complete : ( id : number ) => void
107
+ }
108
+ function TodoItem ( { item, deleteTodo, complete } : TodoItemProps ) {
109
+ return (
110
+ < div className = "bg-blue-50 px-4 py-2 rounded-full shadow mb-4 relative" >
111
+ < button
112
+ type = "button"
113
+ onClick = { ( ) => deleteTodo ( item . id ) }
114
+ className = "absolute top-3 right-3"
115
+ >
116
+ < Delete />
117
+ </ button >
118
+ < input
119
+ type = "checkbox"
120
+ className = "h-4 w-4 mr-2 -mt-2"
121
+ checked = { item . isCompleted }
122
+ onChange = { ( ) => complete ( item . id ) }
123
+ />
124
+ < span className = { item . isCompleted ? "line-through" : "" } >
125
+ { item . text }
126
+ </ span >
127
+ </ div >
128
+ )
129
+ }
62
130
63
- function TodoItem ( { item } : { item : Todo } ) {
64
- return < div > { item . text } </ div >
131
+ function PlusCircle ( ) {
132
+ return (
133
+ < svg
134
+ xmlns = "http://www.w3.org/2000/svg"
135
+ className = "h-6 w-6"
136
+ fill = "none"
137
+ viewBox = "0 0 24 24"
138
+ stroke = "#4B5563"
139
+ >
140
+ < path
141
+ strokeLinecap = "round"
142
+ strokeLinejoin = "round"
143
+ strokeWidth = { 2 }
144
+ d = "M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
145
+ />
146
+ </ svg >
147
+ )
148
+ }
149
+
150
+ function Delete ( ) {
151
+ return (
152
+ < svg
153
+ xmlns = "http://www.w3.org/2000/svg"
154
+ className = "h-4 w-4"
155
+ fill = "none"
156
+ viewBox = "0 0 24 24"
157
+ stroke = "#4B5563"
158
+ >
159
+ < path
160
+ strokeLinecap = "round"
161
+ strokeLinejoin = "round"
162
+ strokeWidth = { 2 }
163
+ d = "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
164
+ />
165
+ </ svg >
166
+ )
65
167
}
66
168
67
169
export default TodoList
0 commit comments