@@ -9,45 +9,35 @@ import Foundation
99
1010final class HomeViewModel : Store {
1111 struct State {
12- // UI
1312 var todoKindPreferences = TodoKind . allCases. map { TodoKindPreference ( kind: $0, isVisible: true ) }
1413 var pinnedTodos : [ Todo ] = [ ]
1514 var showTodoKindPicker : Bool = false
1615 var showTodoEditor : Bool = false
1716 var showSearchView : Bool = false
1817 var selectedTodoKind : TodoKind ?
19-
20- // User Input
2118 var searchText : String = " "
2219 var isSearching : Bool = false
2320 var reorderTodo : Bool = false
24-
25- // Side Effect UI
2621 var isLoading : Bool = false
27- var toastMessage : String = " "
28- var showToast : Bool = false
22+ var showAlert : Bool = false
23+ var alertTitle : String = " "
24+ var alertMessage : String = " "
2925 }
3026
3127 enum Action {
32- // Life Cycle
33- case onAppear
34-
35- // User
3628 case tapTodoKind( TodoKind )
37- case upsertTodo( Todo )
3829 case orderTodoKindPreferences( [ TodoKindPreference ] )
39-
40- // Binding
41- case updateSearching( Bool )
42- case updateSearchText( String )
4330 case setReorderTodo( Bool )
4431 case setShowTodoEditor( Bool )
4532 case setShowTodoKindPicker( Bool )
4633 case setShowSearchView( Bool )
47- case setShowToast( Bool )
48-
49- // Call from run
50- case didFetchPinnedTodos( [ Todo ] )
34+ case setAlert( Bool )
35+ case onAppear
36+ case updateSearching( Bool )
37+ case updateSearchText( String )
38+ case upsertTodo( Todo )
39+ case fetchPinnedTodos( [ Todo ] )
40+ case setLoading( Bool )
5141 }
5242
5343 enum SideEffect {
@@ -69,53 +59,115 @@ final class HomeViewModel: Store {
6959
7060 func reduce( with action: Action ) -> [ SideEffect ] {
7161 var state = self . state
62+ var effects : [ SideEffect ] = [ ]
63+
7264 switch action {
73- case . onAppear:
74- return [ . fetchPinnedTodos]
75- case . tapTodoKind( let kind) :
76- state. selectedTodoKind = kind
77- state. showTodoKindPicker = false
78- state. showTodoEditor = true
79- case . updateSearching( let value) :
80- state. isSearching = value
81- case . updateSearchText( let value) :
82- state. searchText = value
83- case . setReorderTodo( let value) :
84- state. reorderTodo = value
85- case . setShowTodoEditor( let value) :
86- state. showTodoEditor = value
87- if !value {
88- state. selectedTodoKind = nil
89- }
90- case . setShowTodoKindPicker( let value) :
91- state. showTodoKindPicker = value
92- case . setShowSearchView( let value) :
93- state. showSearchView = value
94- case . setShowToast( let value) :
95- state. showToast = value
96- case . upsertTodo( let value) :
97- return [ . upsertTodo( value) ]
98- case . orderTodoKindPreferences( let value) :
99- state. todoKindPreferences = value
100- case . didFetchPinnedTodos( let todos) :
101- state. pinnedTodos = todos
65+ case . tapTodoKind, . orderTodoKindPreferences, . setReorderTodo,
66+ . setShowTodoEditor, . setShowTodoKindPicker, . setShowSearchView, . setAlert:
67+ effects = reduceByUser ( action, state: & state)
68+
69+ case . onAppear, . updateSearching, . updateSearchText, . upsertTodo:
70+ effects = reduceByView ( action, state: & state)
71+
72+ case . fetchPinnedTodos, . setLoading:
73+ effects = reduceByRun ( action, state: & state)
10274 }
10375
10476 self . state = state
105- return [ ]
77+ return effects
10678 }
10779
10880 func run( _ effect: SideEffect ) {
10981 switch effect {
11082 case . upsertTodo( let todo) :
11183 Task {
112- try await upsertTodoUseCase. execute ( todo)
84+ do {
85+ defer { send ( . setLoading( false ) ) }
86+ send ( . setLoading( true ) )
87+ try await upsertTodoUseCase. execute ( todo)
88+ } catch {
89+ send ( . setAlert( true ) )
90+ }
11391 }
11492 case . fetchPinnedTodos:
11593 Task {
116- let todos = try await fetchPinnedTodosUseCase. execute ( )
117- send ( . didFetchPinnedTodos( todos) )
94+ do {
95+ defer { send ( . setLoading( false ) ) }
96+ send ( . setLoading( true ) )
97+ let todos = try await fetchPinnedTodosUseCase. execute ( )
98+ send ( . fetchPinnedTodos( todos) )
99+ } catch {
100+ send ( . setAlert( true ) )
101+ }
118102 }
119103 }
120104 }
121105}
106+
107+ // MARK: - Reduce Methods
108+ private extension HomeViewModel {
109+ func reduceByUser( _ action: Action , state: inout State ) -> [ SideEffect ] {
110+ switch action {
111+ case . tapTodoKind( let kind) :
112+ state. selectedTodoKind = kind
113+ state. showTodoKindPicker = false
114+ state. showTodoEditor = true
115+ case . orderTodoKindPreferences( let preferences) :
116+ state. todoKindPreferences = preferences
117+ case . setReorderTodo( let isPresented) :
118+ state. reorderTodo = isPresented
119+ case . setShowTodoEditor( let isPresented) :
120+ state. showTodoEditor = isPresented
121+ if !isPresented { state. selectedTodoKind = nil }
122+ case . setShowTodoKindPicker( let isPresented) :
123+ state. showTodoKindPicker = isPresented
124+ case . setShowSearchView( let isPresented) :
125+ state. showSearchView = isPresented
126+ case . setAlert( let isPresented) :
127+ setAlert ( & state, isPresented: isPresented)
128+ default :
129+ break
130+ }
131+ return [ ]
132+ }
133+
134+ func reduceByView( _ action: Action , state: inout State ) -> [ SideEffect ] {
135+ switch action {
136+ case . onAppear:
137+ return [ . fetchPinnedTodos]
138+ case . updateSearching( let isSearching) :
139+ state. isSearching = isSearching
140+ case . updateSearchText( let text) :
141+ state. searchText = text
142+ case . upsertTodo( let todo) :
143+ return [ . upsertTodo( todo) ]
144+ default :
145+ break
146+ }
147+ return [ ]
148+ }
149+
150+ func reduceByRun( _ action: Action , state: inout State ) -> [ SideEffect ] {
151+ switch action {
152+ case . fetchPinnedTodos( let todos) :
153+ state. pinnedTodos = todos
154+ case . setLoading( let isLoading) :
155+ state. isLoading = isLoading
156+ default :
157+ break
158+ }
159+ return [ ]
160+ }
161+ }
162+
163+ // MARK: - Helper Methods
164+ private extension HomeViewModel {
165+ func setAlert(
166+ _ state: inout State ,
167+ isPresented: Bool
168+ ) {
169+ state. alertTitle = " 오류 "
170+ state. alertMessage = " 문제가 발생했습니다. 잠시 후 다시 시도해주세요. "
171+ state. showAlert = isPresented
172+ }
173+ }
0 commit comments