Files
todos/App/Previews/Modifiers/SampleTaskDataModifier.swift
T

129 lines
4.4 KiB
Swift
Raw Normal View History

2026-02-10 02:22:41 +00:00
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 tasks: [Todo] = [
.init(
2026-02-10 15:31:52 +00:00
title: "Today task #1",
due: .now
2026-02-10 02:22:41 +00:00
),
.init(
2026-02-10 15:31:52 +00:00
title: "Today task #2",
2026-02-10 02:22:41 +00:00
note: "This is some random note attached to the task.",
2026-02-10 15:31:52 +00:00
due: .now
2026-02-10 02:22:41 +00:00
),
.init(
title: "Tomorrow task",
2026-02-10 15:31:52 +00:00
due: calendar.date(byAdding: .day, value: 1, to: .now) ?? .now
2026-02-10 02:22:41 +00:00
),
.init(
title: "Next week task",
note: "This is some random note attached to the task.",
2026-02-10 15:31:52 +00:00
due: calendar.date(byAdding: .day, value: 7, to: .now) ?? .now
2026-02-10 02:22:41 +00:00
),
.init(
title: "Yesterday task",
2026-02-10 15:31:52 +00:00
due: calendar.date(byAdding: .day, value: -1, to: .now) ?? .now
2026-02-10 02:22:41 +00:00
),
.init(
title: "Last week task",
note: "This is some random note attached to the task.",
2026-02-10 15:31:52 +00:00
due: calendar.date(byAdding: .day, value: -7, to: .now) ?? .now
2026-02-10 02:22:41 +00:00
),
.init(
2026-02-10 15:31:52 +00:00
title: "Completed task #1",
due: calendar.date(byAdding: .day, value: 1, to: .now) ?? .now,
completed: .now
2026-02-10 02:22:41 +00:00
),
.init(
2026-02-10 15:31:52 +00:00
title: "Completed task #2",
2026-02-10 02:22:41 +00:00
note: "This is some random note attached to the task.",
2026-02-10 15:31:52 +00:00
due: calendar.date(byAdding: .day, value: -1, to: .now) ?? .now,
completed: .now
2026-02-10 02:22:41 +00:00
),
]
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())
}