diff --git a/DevLog/Data/Protocol/Dictionaryable.swift b/DevLog/Data/Protocol/Dictionaryable.swift index 251ab09..fd7e1c8 100644 --- a/DevLog/Data/Protocol/Dictionaryable.swift +++ b/DevLog/Data/Protocol/Dictionaryable.swift @@ -5,7 +5,7 @@ // Created by 최윤진 on 12/14/25. // -import Foundation +import FirebaseFirestore protocol Dictionaryable: Encodable { func toDictionary() -> [String: Any] @@ -13,11 +13,23 @@ protocol Dictionaryable: Encodable { extension Dictionaryable { func toDictionary() -> [String: Any] { - guard let encodedData = try? JSONEncoder().encode(self), - var dictionary = (try? JSONSerialization.jsonObject(with: encodedData)) as? [String: Any] - else { return [:] } + let encoder = Firestore.Encoder() + guard var dictionary = try? encoder.encode(self) else { return [:] } + + let mirror = Mirror(reflecting: self) + for child in mirror.children { + guard let key = child.label else { continue } + if isNilValue(child.value) { + dictionary[key] = NSNull() + } + } dictionary.removeValue(forKey: "id") return dictionary } + + private func isNilValue(_ value: Any) -> Bool { + let mirror = Mirror(reflecting: value) + return mirror.displayStyle == .optional && mirror.children.isEmpty + } } diff --git a/DevLog/Presentation/ViewModel/TodoViewModel.swift b/DevLog/Presentation/ViewModel/TodoViewModel.swift index f60e833..cad300c 100644 --- a/DevLog/Presentation/ViewModel/TodoViewModel.swift +++ b/DevLog/Presentation/ViewModel/TodoViewModel.swift @@ -131,7 +131,18 @@ final class TodoViewModel: Store { } } case .togglePinned(let todo): - break + Task { + do { + defer { send(.didLoading(false)) } + send(.didLoading(true)) + var todo = todo + todo.isPinned.toggle() + try await upsertTodoUseCase.execute(todo) + send(.didTogglePinned(todo)) + } catch { + send(.didShowAlert(error.localizedDescription)) + } + } case .swipeTodo(let todo): break }