import SwiftData import SwiftUI /// A view for creating new todo tasks. /// /// This view provides a form interface for users to input todo task details including: /// - *Title* (required) /// - *Note* (optional) /// - *Due date* (required) /// /// The view uses a dedicated view model (`ViewModel`) to manage state and business logic, following the MVVM pattern. /// When the user saves, the todo is inserted into the SwiftData model context and the view is dismissed afterwards. struct NewTaskView: View { // MARK: Properties /// Environment value for dismissing this view. @Environment(\.dismiss) private var dismiss /// SwiftData model context for saving todo tasks. @Environment(\.modelContext) private var modelContext /// The view model managing the state and logic for this view. @State private var viewModel: ViewModel // MARK: Initialization /// Initializes a new task view with a fresh view model instance. init() { _viewModel = State(initialValue: .init()) } // MARK: Body /// The content and behavior of the view. /// /// Displays a navigation stack containing a form with sections for: /// - Task details (title and note fields) /// - Due date picker with graphical style /// /// The toolbar includes: /// - Cancel button to dismiss without saving /// - Confirm button to persist the todo and dismiss (disabled when title is empty) var body: some View { NavigationStack { Form { Section("view.new-task.section.task") { TextField( "view.new-task.placeholder.title", text: $viewModel.title, axis: .vertical ) .autocapitalization(.sentences) .autocorrectionDisabled(false) .keyboardType(.asciiCapable) TextField( "view.new-task.placeholder.note", text: $viewModel.note, axis: .vertical ) .autocapitalization(.sentences) .autocorrectionDisabled(false) .keyboardType(.asciiCapable) .lineLimit(3 ... 6) } Section("view.new-task.section.due-date") { DatePicker( "view.new-task.placeholder.due-date", selection: $viewModel.due, displayedComponents: [.date] ) .datePickerStyle(.graphical) } } .navigationTitle("view.new-task.navigation.title") .navigationBarTitleDisplayMode(.inline) .onResignFocus() .toolbar { ToolbarItem(placement: .cancellationAction) { Button(role: .cancel) { dismiss() } } ToolbarItem(placement: .confirmationAction) { Button(role: .confirm) { viewModel.save(to: modelContext) dismiss() } .disabled(!viewModel.canConfirm) } } } } } // MARK: - Previews #Preview( "New todo task", traits: .emptyContainer ) { NewTaskView() }