import SwiftData import SwiftUI /// A preview modifier that provides sample task data for SwiftUI previews. /// /// This modifier creates an in-memory SwiftData model container populated with representative sample todos across all task groups /// (today, upcoming, overdue, completed). /// It's designed to be used with SwiftUI previews to display realistic data without /// requiring a persistent database. /// /// ## Usage /// Use the `.sampleTasks` trait on your preview: /// /// ```swift /// #Preview(traits: .sampleTasks) { /// TaskGroupListView() /// } /// ``` /// /// This automatically provides a model container with sample data to the preview. struct SampleTaskDataModifier: PreviewModifier { // MARK: Functions /// Creates and configures a shared in-memory model container with sample task data. /// /// This method is called once when the preview is loaded and creates an in-memory /// SwiftData container populated with 8 representative todo tasks spanning all /// task groups and various configurations. /// /// - Returns: A `ModelContainer` configured for in-memory storage with sample data. /// - Throws: An error if the model container cannot be created. static func makeSharedContext() async throws -> ModelContainer { let modelContainer = try ModelContainer( for: Todo.self, configurations: .init(isStoredInMemoryOnly: true) ) let calendar: Calendar = .current let today: Date = .now let tomorrow: Date = calendar.date(byAdding: .day, value: 1, to: today) ?? today let yesterday = calendar.date(byAdding: .day, value: -1, to: today) ?? today let tasks: [Todo] = [ .init( title: "Today task 1", due: today ), .init( title: "Today task 2", note: "This is some random note attached to the task.", due: today ), .init( title: "Tomorrow task", due: tomorrow ), .init( title: "Next week task", note: "This is some random note attached to the task.", due: calendar.date(byAdding: .day, value: 7, to: today) ?? today ), .init( title: "Yesterday task", due: yesterday ), .init( title: "Last week task", note: "This is some random note attached to the task.", due: calendar.date(byAdding: .day, value: -7, to: today) ?? today ), .init( title: "Completed task 1", due: today, completed: today ), .init( title: "Completed task 2", note: "This is some random note attached to the task.", due: yesterday, completed: today ), ] for task in tasks { modelContainer.mainContext.insert(task) } return modelContainer } /// Applies the model container to the preview content. /// /// This method is called by SwiftUI to apply the modifier to the preview. /// It injects the model container into the SwiftUI environment, making it /// available to any views that use `@Query` or `@Environment(\.modelContext)`. /// /// - Parameters: /// - content: The preview content to modify. /// - context: The model container with sample data. /// - Returns: The content with the model container applied. func body( content: Content, context: ModelContainer ) -> some View { content.modelContainer(context) } } // MARK: - PreviewTrait extension PreviewTrait where T == Preview.ViewTraits { /// A preview trait that provides sample task data. /// /// Use this trait to automatically populate previews with realistic sample todos /// without manually creating a model container and inserting data. /// /// ## Example /// ```swift /// #Preview(traits: .sampleTasks) { /// TaskGroupListView() /// } /// ``` /// /// This is equivalent to manually creating a container with sample data but /// much more concise and reusable across multiple previews. static var sampleTasks: Self = .modifier(SampleTaskDataModifier()) }