import SwiftData import SwiftUI extension NewTaskView { /// View model for managing the logic for creating todo tasks. /// /// This observable class encapsulates the state and business logic for creating new todo tasks. /// It follows the MVVM pattern to separate presentation logic from the view layer. /// /// The view model manages: /// - User input for task title, note, and due date /// - Form validation (ensuring title is not empty) /// - Saving the todo to SwiftData model context @Observable final class ViewModel { // MARK: Properties /// The title of the todo task. /// /// This is a required field. The save button is disabled when this is empty. var title: String /// A note providing additional details about the task, if required. /// /// If left empty, the note will be stored as `nil` in the model. var note: String /// The due date for the todo task. /// /// Defaults to the current date when the view model is initialized. var due: Date // MARK: Initialization /// Initializes a new view model instance with default values. /// /// The view model is initialized with: /// - Empty title /// - Empty note /// - Current date as due date init() { title = "" note = "" due = .init() } // MARK: Computed /// Whether the confirmation button should be enabled. /// /// Returns `true` when the title is not empty after trimming whitespace, `false` otherwise. var canConfirm: Bool { !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } // MARK: Functions /// Saves a new todo task to the SwiftData model context. /// /// This function creates a new `Todo` instance with the current property values and inserts it into the provided model context. /// The title and note are trimmed of leading and trailing whitespace before saving. /// The `note` property value is only included if it's not empty after trimming. /// /// - Parameter modelContext: The SwiftData model context to insert a new todo task. func save(to modelContext: ModelContext) { let trimmedTitle = title.trimmingCharacters(in: .whitespacesAndNewlines) let trimmedNote = note.trimmingCharacters(in: .whitespacesAndNewlines) let todo = Todo( title: trimmedTitle, note: trimmedNote.isEmpty ? nil : trimmedNote, due: due ) modelContext.insert(todo) } } }