@@ -37,6 +37,7 @@ final class TodoListViewModel: Store {
3737 case setShowEditor( Bool )
3838 case swipeTodo( TodoListItem )
3939 case tapFilterOption( FilterOption )
40+ case tapToggleCompleted( TodoListItem )
4041 case tapTogglePinned( TodoListItem )
4142 case undoDelete
4243
@@ -50,6 +51,7 @@ final class TodoListViewModel: Store {
5051 case upsertTodo( Todo )
5152
5253 // Run
54+ case didToggleCompleted( TodoListItem )
5355 case didTogglePinned( TodoListItem )
5456 case setLoading( Bool )
5557 case appendTodos( [ TodoListItem ] , nextCursor: TodoCursor ? )
@@ -62,6 +64,7 @@ final class TodoListViewModel: Store {
6264 case loadNextPage
6365 case upsert( Todo )
6466 case delete( String )
67+ case toggleCompleted( TodoListItem )
6568 case togglePinned( TodoListItem )
6669 }
6770
@@ -91,13 +94,13 @@ final class TodoListViewModel: Store {
9194 var effects : [ SideEffect ] = [ ]
9295
9396 switch action {
94- case . refresh, . setAlert, . setShowEditor, . swipeTodo, . tapFilterOption, . tapTogglePinned, . undoDelete:
97+ case . refresh, . setAlert, . setShowEditor, . swipeTodo, . tapFilterOption, . tapToggleCompleted , . tapTogglePinned, . undoDelete:
9598 effects = reduceByUser ( action, state: & state)
9699
97100 case . confirmDelete, . onAppear, . loadNextPage, . setScope, . setSearchText, . setToast, . upsertTodo:
98101 effects = reduceByView ( action, state: & state)
99102
100- case . didTogglePinned, . setLoading, . appendTodos, . resetPagination, . setHasMore:
103+ case . didToggleCompleted , . didTogglePinned, . setLoading, . appendTodos, . resetPagination, . setHasMore:
101104 effects = reduceByRun ( action, state: & state)
102105 }
103106
@@ -145,6 +148,22 @@ final class TodoListViewModel: Store {
145148 send ( . setAlert( true ) )
146149 }
147150 }
151+ case . toggleCompleted( let item) :
152+ Task {
153+ do {
154+ defer { send ( . setLoading( false ) ) }
155+ send ( . setLoading( true ) )
156+ var todo = try await fetchTodoByIDUseCase. execute ( item. id)
157+ let now = Date ( )
158+ todo. isCompleted. toggle ( )
159+ todo. completedAt = todo. isCompleted ? now : nil
160+ todo. updatedAt = now
161+ try await upsertTodoUseCase. execute ( todo)
162+ send ( . didToggleCompleted( TodoListItem ( from: todo) ) )
163+ } catch {
164+ send ( . setAlert( true ) )
165+ }
166+ }
148167 case . togglePinned( let item) :
149168 Task {
150169 do {
@@ -195,6 +214,8 @@ private extension TodoListViewModel {
195214 return effects
196215 case . tapFilterOption( let option) :
197216 state. filterOption = option
217+ case . tapToggleCompleted( let todo) :
218+ return [ . toggleCompleted( todo) ]
198219 case . tapTogglePinned( let todo) :
199220 return [ . togglePinned( todo) ]
200221 case . undoDelete:
@@ -238,6 +259,10 @@ private extension TodoListViewModel {
238259
239260 func reduceByRun( _ action: Action , state: inout State ) -> [ SideEffect ] {
240261 switch action {
262+ case . didToggleCompleted( let todo) :
263+ if let index = state. todos. firstIndex ( where: { $0. id == todo. id } ) {
264+ state. todos [ index] = todo
265+ }
241266 case . didTogglePinned( let todo) :
242267 if let index = state. todos. firstIndex ( where: { $0. id == todo. id } ) {
243268 state. todos [ index] = todo
0 commit comments