diff --git a/DevLog/Presentation/ViewModel/TodoEditorViewModel.swift b/DevLog/Presentation/ViewModel/TodoEditorViewModel.swift index 0d215c3c..55a40aed 100644 --- a/DevLog/Presentation/ViewModel/TodoEditorViewModel.swift +++ b/DevLog/Presentation/ViewModel/TodoEditorViewModel.swift @@ -10,6 +10,27 @@ import OrderedCollections @Observable final class TodoEditorViewModel: Store { + private struct Draft: Equatable { + let title: String + let content: String + let dueDate: Date? + let tags: [String] + + init(todo: Todo) { + self.title = todo.title + self.content = todo.content + self.dueDate = todo.dueDate + self.tags = todo.tags + } + + init(state: State) { + self.title = state.title + self.content = state.content + self.dueDate = state.dueDate + self.tags = Array(state.tags) + } + } + struct State: Equatable { var title: String = "" var content: String = "" @@ -52,6 +73,16 @@ final class TodoEditorViewModel: Store { private let createdAt: Date? private let completedAt: Date? private let kind: TodoKind + private let originalDraft: Draft? + + var hasChanges: Bool { + guard let originalDraft else { return true } + return originalDraft != Draft(state: state) + } + + var isReadyToSubmit: Bool { + state.isValidToSave && hasChanges + } // 새로운 Todo 생성용 생성자 init(kind: TodoKind) { @@ -63,6 +94,7 @@ final class TodoEditorViewModel: Store { self.createdAt = nil self.completedAt = nil self.kind = kind + self.originalDraft = nil } // 기존 Todo 편집용 생성자 @@ -75,6 +107,7 @@ final class TodoEditorViewModel: Store { self.createdAt = todo.createdAt self.completedAt = todo.completedAt self.kind = todo.kind + self.originalDraft = Draft(todo: todo) state.title = todo.title state.content = todo.content state.dueDate = todo.dueDate @@ -134,7 +167,7 @@ extension TodoEditorViewModel { } } - func upsertTodo() -> Todo { + func makeTodo() -> Todo { let date = Date() return Todo( id: self.id, diff --git a/DevLog/UI/Home/TodoEditorView.swift b/DevLog/UI/Home/TodoEditorView.swift index e47e1997..72e9c4be 100644 --- a/DevLog/UI/Home/TodoEditorView.swift +++ b/DevLog/UI/Home/TodoEditorView.swift @@ -47,14 +47,11 @@ struct TodoEditorView: View { .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.background, for: .navigationBar) .toolbar { - ToolbarLeadingButton { - dismiss() - } + ToolbarLeadingButton { dismiss() } ToolbarTrailingButton { - onSubmit?(viewModel.upsertTodo()) - dismiss() + submit() } - .disabled(!viewModel.state.isValidToSave) + .disabled(!viewModel.isReadyToSubmit) } } } @@ -166,25 +163,10 @@ struct TodoEditorView: View { } } - @ToolbarContentBuilder - private var toolBar: some ToolbarContent { - ToolbarItem(placement: .topBarLeading) { - Button { - dismiss() - } label: { - Image(systemName: "xmark") - .bold() - } - } - ToolbarItem(placement: .topBarTrailing) { - Button(action: { - onSubmit?(viewModel.upsertTodo()) - dismiss() - }) { - Text("추가") - } - .disabled(!viewModel.state.isValidToSave) - } + private func submit() { + let todo = viewModel.makeTodo() + onSubmit?(todo) + dismiss() } private enum Field: Hashable {