Skip to content

Commit 5d877ba

Browse files
committed
refactor: Todo 생성 수정 저장 흐름 분리
1 parent 3fde8d6 commit 5d877ba

9 files changed

Lines changed: 91 additions & 44 deletions

Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ final class HomeViewCoordinator {
4343

4444
cancellable = windowEvent.submits
4545
.sink { [weak self] submit in
46-
guard submit.value.matchesCreate(source: .home) else { return }
46+
guard case .create(let value) = submit,
47+
value.matchesCreate(source: .home) else { return }
4748
self?.viewModel.send(.fetchData)
4849
}
4950
}
@@ -59,7 +60,7 @@ final class HomeViewCoordinator {
5960
fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self),
6061
upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self),
6162
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
62-
onUpsertSuccess: { [weak self] _ in
63+
onCreateSuccess: { [weak self] in
6364
self?.viewModel.send(.setPresentation(.todoEditor, false))
6465
self?.viewModel.send(.fetchData)
6566
}

Application/DevLogPresentation/Sources/Home/TodoDetailView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ struct TodoDetailView: View {
1818
var body: some View {
1919
ZStack {
2020
Color(.systemGroupedBackground).ignoresSafeArea()
21-
if let todo = viewModel.state.todo, let number = todo.number {
21+
if let todo = viewModel.state.todo {
2222
TodoDetailContentView(
2323
title: todo.title,
2424
content: todo.content,
2525
referenceItems: viewModel.state.referenceItems,
26-
number: number,
26+
number: todo.number,
2727
onOpenTodoID: { viewModel.send(.setSelectedTodoId(TodoIdItem(id: $0))) }
2828
)
2929
} else if viewModel.state.isLoading {
@@ -69,7 +69,7 @@ struct TodoDetailView: View {
6969
fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self),
7070
fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self),
7171
upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self),
72-
onUpsertSuccess: { todo in
72+
onUpdateSuccess: { todo in
7373
viewModel.send(.setShowEditor(false))
7474
viewModel.send(.setTodo(todo))
7575
}

Application/DevLogPresentation/Sources/Home/TodoEditorView.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,7 @@ struct TodoEditorView: View {
208208
}
209209

210210
private func submit() {
211-
let todo = viewModel.makeTodo()
212-
viewModel.send(.upsertTodo(todo))
211+
viewModel.send(.upsertTodo)
213212
}
214213

215214
private func close() {

Application/DevLogPresentation/Sources/Home/TodoEditorViewModel.swift

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,14 @@ final class TodoEditorViewModel: Store {
9191
case setTitle(String)
9292
case setCategories([TodoCategoryItem])
9393
case setReferenceItems([Int: TodoReferenceItem])
94-
case upsertTodo(Todo)
94+
case upsertTodo
9595
}
9696

9797
enum SideEffect {
9898
case fetchCategories
9999
case resolveMarkdown(String)
100-
case upsertTodo(Todo)
100+
case createTodo(TodoDraft)
101+
case updateTodo(Todo)
101102
}
102103

103104
private(set) var state = State()
@@ -106,7 +107,8 @@ final class TodoEditorViewModel: Store {
106107
private let fetchReferenceItemsUseCase: FetchReferenceItemsUseCase
107108
private let upsertTodoUseCase: UpsertTodoUseCase
108109
private let trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase?
109-
private let onUpsertSuccess: ((Todo) -> Void)?
110+
private let onCreateSuccess: (() -> Void)?
111+
private let onUpdateSuccess: ((Todo) -> Void)?
110112
private let id: String
111113
private let isCompleted: Bool
112114
private let isChecked: Bool
@@ -142,13 +144,14 @@ final class TodoEditorViewModel: Store {
142144
fetchReferenceItemsUseCase: FetchReferenceItemsUseCase,
143145
upsertTodoUseCase: UpsertTodoUseCase,
144146
trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase? = nil,
145-
onUpsertSuccess: ((Todo) -> Void)? = nil
147+
onCreateSuccess: (() -> Void)? = nil
146148
) {
147149
self.fetchPreferencesUseCase = fetchPreferencesUseCase
148150
self.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase
149151
self.upsertTodoUseCase = upsertTodoUseCase
150152
self.trackAnalyticsEventUseCase = trackAnalyticsEventUseCase
151-
self.onUpsertSuccess = onUpsertSuccess
153+
self.onCreateSuccess = onCreateSuccess
154+
self.onUpdateSuccess = nil
152155
self.id = UUID().uuidString
153156
self.isCompleted = false
154157
self.isChecked = false
@@ -167,13 +170,14 @@ final class TodoEditorViewModel: Store {
167170
fetchReferenceItemsUseCase: FetchReferenceItemsUseCase,
168171
upsertTodoUseCase: UpsertTodoUseCase,
169172
trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase? = nil,
170-
onUpsertSuccess: ((Todo) -> Void)? = nil
173+
onUpdateSuccess: ((Todo) -> Void)? = nil
171174
) {
172175
self.fetchPreferencesUseCase = fetchPreferencesUseCase
173176
self.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase
174177
self.upsertTodoUseCase = upsertTodoUseCase
175178
self.trackAnalyticsEventUseCase = trackAnalyticsEventUseCase
176-
self.onUpsertSuccess = onUpsertSuccess
179+
self.onCreateSuccess = nil
180+
self.onUpdateSuccess = onUpdateSuccess
177181
self.id = todo.id
178182
self.isCompleted = todo.isCompleted
179183
self.isChecked = todo.isChecked
@@ -243,8 +247,12 @@ final class TodoEditorViewModel: Store {
243247
state.categories = categories
244248
case .setReferenceItems(let items):
245249
state.referenceItems = items
246-
case .upsertTodo(let todo):
247-
effects = [.upsertTodo(todo)]
250+
case .upsertTodo:
251+
if originalDraft == nil {
252+
effects = [.createTodo(makeTodoDraft())]
253+
} else if let todo = makeTodo() {
254+
effects = [.updateTodo(todo)]
255+
}
248256
}
249257

250258
if self.state != state { self.state = state }
@@ -276,16 +284,25 @@ final class TodoEditorViewModel: Store {
276284

277285
send(.setReferenceItems(referenceItems))
278286
}
279-
case .upsertTodo(let todo):
287+
case .createTodo(let todoDraft):
288+
send(.setLoading(true))
289+
Task {
290+
do {
291+
defer { send(.setLoading(false)) }
292+
try await upsertTodoUseCase.execute(todoDraft)
293+
trackAnalyticsEventUseCase?.execute(.todoCreate)
294+
onCreateSuccess?()
295+
} catch {
296+
send(.setAlert(true))
297+
}
298+
}
299+
case .updateTodo(let todo):
280300
send(.setLoading(true))
281301
Task {
282302
do {
283303
defer { send(.setLoading(false)) }
284304
try await upsertTodoUseCase.execute(todo)
285-
if originalDraft == nil {
286-
trackAnalyticsEventUseCase?.execute(.todoCreate)
287-
}
288-
onUpsertSuccess?(todo)
305+
onUpdateSuccess?(todo)
289306
} catch {
290307
send(.setAlert(true))
291308
}
@@ -321,17 +338,36 @@ extension TodoEditorViewModel {
321338
state.showAlert = isPresented
322339
}
323340

324-
func makeTodo() -> Todo {
341+
private func makeTodoDraft() -> TodoDraft {
342+
let date = Date()
343+
return TodoDraft(
344+
id: self.id,
345+
isPinned: state.isPinned,
346+
isCompleted: state.isCompleted,
347+
isChecked: self.isChecked,
348+
title: state.title,
349+
content: state.content,
350+
createdAt: date,
351+
updatedAt: date,
352+
completedAt: state.completedAt,
353+
dueDate: state.dueDate,
354+
tags: state.tags.map { $0 },
355+
category: state.category.category
356+
)
357+
}
358+
359+
private func makeTodo() -> Todo? {
360+
guard let number, let createdAt else { return nil }
325361
let date = Date()
326362
return Todo(
327363
id: self.id,
328364
isPinned: state.isPinned,
329365
isCompleted: state.isCompleted,
330366
isChecked: self.isChecked,
331-
number: self.number,
367+
number: number,
332368
title: state.title,
333369
content: state.content,
334-
createdAt: self.createdAt ?? date,
370+
createdAt: createdAt,
335371
updatedAt: date,
336372
completedAt: state.completedAt,
337373
deletedAt: self.deletedAt,

Application/DevLogPresentation/Sources/Home/TodoEditorWindowEvent.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ public final class TodoEditorWindowEvent {
1717

1818
public init() { }
1919

20-
func submit(
20+
func submitCreate(value: TodoEditorWindowValue) {
21+
subject.send(.create(value))
22+
}
23+
24+
func submitUpdate(
2125
value: TodoEditorWindowValue,
2226
todo: Todo
2327
) {
24-
subject.send(TodoEditorWindowSubmit(value: value, todo: todo))
28+
subject.send(.update(value, todo))
2529
}
2630
}

Application/DevLogPresentation/Sources/Home/TodoEditorWindowValue.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public struct TodoEditorWindowTodo: Codable, Hashable {
7777
private let isPinned: Bool
7878
private let isCompleted: Bool
7979
private let isChecked: Bool
80-
private let number: Int?
80+
private let number: Int
8181
private let title: String
8282
private let content: String
8383
private let createdAt: Date
@@ -136,10 +136,9 @@ public struct TodoEditorWindowTodo: Codable, Hashable {
136136
}
137137
}
138138

139-
struct TodoEditorWindowSubmit: Equatable {
140-
let id = UUID()
141-
let value: TodoEditorWindowValue
142-
let todo: Todo
139+
enum TodoEditorWindowSubmit: Equatable {
140+
case create(TodoEditorWindowValue)
141+
case update(TodoEditorWindowValue, Todo)
143142
}
144143

145144
extension TodoEditorWindowValue {

Application/DevLogPresentation/Sources/Home/TodoEditorWindowView.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public struct TodoEditorWindowView: View {
3434
fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self),
3535
upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self),
3636
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
37-
onUpsertSuccess: upsert
37+
onCreateSuccess: create
3838
),
3939
onClose: closeWindow
4040
)
@@ -45,7 +45,7 @@ public struct TodoEditorWindowView: View {
4545
fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self),
4646
fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self),
4747
upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self),
48-
onUpsertSuccess: upsert
48+
onUpdateSuccess: update
4949
),
5050
onClose: closeWindow
5151
)
@@ -56,8 +56,13 @@ public struct TodoEditorWindowView: View {
5656
}
5757
}
5858

59-
private func upsert(_ todo: Todo) {
60-
windowEvent.submit(value: value, todo: todo)
59+
private func create() {
60+
windowEvent.submitCreate(value: value)
61+
closeWindow()
62+
}
63+
64+
private func update(_ todo: Todo) {
65+
windowEvent.submitUpdate(value: value, todo: todo)
6166
closeWindow()
6267
}
6368

Application/DevLogPresentation/Sources/Home/TodoListView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ struct TodoListView: View {
8787
fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self),
8888
upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self),
8989
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
90-
onUpsertSuccess: { _ in
90+
onCreateSuccess: {
9191
viewModel.send(.setShowEditor(false))
9292
viewModel.send(.refresh)
9393
}

Application/DevLogPresentation/Sources/Home/TodoWindowCoordinator.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,17 @@ final class TodoWindowCoordinator {
7474
}
7575

7676
private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit) {
77-
if let listViewModel,
78-
submit.value.matchesCreate(category: listViewModel.category, source: .list) {
79-
listViewModel.send(.refresh)
80-
}
81-
82-
if let detailViewModel,
83-
submit.value.matchesEdit(todoId: detailViewModel.todoId) {
84-
detailViewModel.send(.setTodo(submit.todo))
77+
switch submit {
78+
case .create(let value):
79+
if let listViewModel,
80+
value.matchesCreate(category: listViewModel.category, source: .list) {
81+
listViewModel.send(.refresh)
82+
}
83+
case .update(let value, let todo):
84+
if let detailViewModel,
85+
value.matchesEdit(todoId: detailViewModel.todoId) {
86+
detailViewModel.send(.setTodo(todo))
87+
}
8588
}
8689
}
8790
}

0 commit comments

Comments
 (0)