1
1
package xyz.junerver.composehooks.example
2
2
3
3
import androidx.compose.foundation.layout.Column
4
+ import androidx.compose.foundation.layout.Row
4
5
import androidx.compose.foundation.layout.Spacer
5
6
import androidx.compose.foundation.layout.height
7
+ import androidx.compose.foundation.layout.width
8
+ import androidx.compose.material3.Button
9
+ import androidx.compose.material3.Checkbox
10
+ import androidx.compose.material3.MaterialTheme
6
11
import androidx.compose.material3.OutlinedTextField
7
12
import androidx.compose.material3.Surface
8
13
import androidx.compose.material3.Text
14
+ import androidx.compose.material3.TextField
9
15
import androidx.compose.runtime.Composable
16
+ import androidx.compose.runtime.getValue
17
+ import androidx.compose.runtime.key
18
+ import androidx.compose.runtime.mutableStateOf
19
+ import androidx.compose.runtime.remember
20
+ import androidx.compose.runtime.setValue
21
+ import androidx.compose.ui.Alignment
10
22
import androidx.compose.ui.Modifier
11
23
import androidx.compose.ui.unit.dp
12
24
import xyz.junerver.compose.hooks.Middleware
@@ -61,6 +73,7 @@ fun UseReducerExample() {
61
73
TButton (text = " +1" ) {
62
74
dispatch(SimpleAction .AgeIncrease )
63
75
}
76
+ TaskApp ()
64
77
}
65
78
}
66
79
}
@@ -74,3 +87,122 @@ fun <S, A> logMiddleware(): Middleware<S, A> {
74
87
}
75
88
}
76
89
}
90
+
91
+ @Composable
92
+ fun TaskList (tasks : List <Task >, onChangeTask : (Task ) -> Unit , onDeleteTask : (Int ) -> Unit ) {
93
+ tasks.forEach { task ->
94
+ key(task.id) {
95
+ TaskItem (task = task, onChange = onChangeTask, onDelete = onDeleteTask)
96
+ }
97
+ }
98
+ }
99
+
100
+ @Composable
101
+ fun TaskItem (task : Task , onChange : (Task ) -> Unit , onDelete : (Int ) -> Unit ) {
102
+ var isEditing by remember { mutableStateOf(false ) }
103
+ var text by remember { mutableStateOf(task.text) }
104
+
105
+ Row (verticalAlignment = Alignment .CenterVertically ) {
106
+ Checkbox (
107
+ checked = task.done,
108
+ onCheckedChange = { checked ->
109
+ onChange(task.copy(done = checked))
110
+ }
111
+ )
112
+
113
+ if (isEditing) {
114
+ TextField (
115
+ modifier = Modifier .width(100 .dp),
116
+ value = text,
117
+ onValueChange = { newText ->
118
+ text = newText
119
+ onChange(task.copy(text = newText))
120
+ }
121
+ )
122
+ Button (onClick = { isEditing = false }) {
123
+ Text (" Save" )
124
+ }
125
+ } else {
126
+ Text (text = task.text)
127
+ Button (onClick = { isEditing = true }) {
128
+ Text (" Edit" )
129
+ }
130
+ }
131
+
132
+ Button (onClick = { onDelete(task.id) }) {
133
+ Text (" Delete" )
134
+ }
135
+ }
136
+ }
137
+
138
+ data class Task (val id : Int , val text : String , val done : Boolean )
139
+
140
+ @Composable
141
+ fun AddTask (onAddTask : (String ) -> Unit ) {
142
+ var text by remember { mutableStateOf(" " ) }
143
+
144
+ Row {
145
+ TextField (
146
+ modifier = Modifier .width(100 .dp),
147
+ value = text,
148
+ onValueChange = { newText ->
149
+ text = newText
150
+ },
151
+ placeholder = { Text (" Add task" ) }
152
+ )
153
+ Button (onClick = {
154
+ onAddTask(text)
155
+ text = " "
156
+ }) {
157
+ Text (" Add" )
158
+ }
159
+ }
160
+ }
161
+
162
+ @Composable
163
+ fun TaskApp () {
164
+ val (tasks, dispatch) = useReducer<List <Task >, TaskAction > (
165
+ { prevState, action ->
166
+ when (action) {
167
+ is TaskAction .Added -> prevState + Task (nextId++ , action.text, false )
168
+ is TaskAction .Changed -> prevState.map { if (it.id == action.task.id) action.task else it }
169
+ is TaskAction .Deleted -> prevState.filter { it.id != action.taskId }
170
+ }
171
+ },
172
+ initialTasks,
173
+ arrayOf(
174
+ logMiddleware()
175
+ )
176
+ )
177
+
178
+ fun handleAddTask (text : String ) {
179
+ dispatch(TaskAction .Added (text))
180
+ }
181
+
182
+ fun handleChangeTask (task : Task ) {
183
+ dispatch(TaskAction .Changed (task))
184
+ }
185
+
186
+ fun handleDeleteTask (taskId : Int ) {
187
+ dispatch(TaskAction .Deleted (taskId))
188
+ }
189
+
190
+ Column {
191
+ Text (text = " Day off in Kyoto" , style = MaterialTheme .typography.titleLarge)
192
+ AddTask (onAddTask = ::handleAddTask)
193
+ TaskList (tasks = tasks, onChangeTask = ::handleChangeTask, onDeleteTask = ::handleDeleteTask)
194
+ }
195
+ }
196
+
197
+ var nextId = 3
198
+ val initialTasks = listOf (
199
+ Task (id = 0 , text = " Philosopher’s Path" , done = true ),
200
+ Task (id = 1 , text = " Visit the temple" , done = false ),
201
+ Task (id = 2 , text = " Drink matcha" , done = false )
202
+ )
203
+
204
+ sealed interface TaskAction {
205
+ data class Added (val text : String ) : TaskAction
206
+ data class Changed (val task : Task ) : TaskAction
207
+ data class Deleted (val taskId : Int ) : TaskAction
208
+ }
0 commit comments