Group tasks feature (#3)

This PR contains the work done to implement the **Group Task** feature, and to integrate it into the main content view of the app. Furthermore, an issue related to triggering a view update after inserting the todo tasks into the model container has been fixed.

Reviewed-on: rock-n-code/todos-app#3
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #3.
This commit is contained in:
2026-02-10 02:22:41 +00:00
committed by javier
parent 5506471fe0
commit 0b8e5d8bd0
16 changed files with 806 additions and 9 deletions
@@ -0,0 +1,79 @@
import SwiftData
import SwiftUI
/// A preview modifier that provides an empty SwiftData model container for SwiftUI previews.
///
/// This modifier creates an in-memory SwiftData model container with no data, useful for testing and previewing views in their empty or initial state.
/// It's particularly helpful for testing empty state UI, loading states, or views that should gracefully handle no data.
///
/// ## Usage
/// Use the `.emptyContainer` trait on your preview:
///
/// ```swift
/// #Preview(traits: .emptyContainer) {
/// TaskGroupListView()
/// }
/// ```
///
/// This automatically provides an empty model container to the preview, allowing SwiftData queries to return empty results.
struct EmptyContainerModifier: PreviewModifier {
// MARK: Functions
/// Creates and configures a shared in-memory model container with no data.
///
/// This method is called once when the preview is loaded and creates an in-memory
/// SwiftData container with no persisted entities. The container is configured
/// to store data only in memory, ensuring previews don't affect any persistent storage.
///
/// - Returns: An empty `ModelContainer` configured for in-memory storage.
/// - Throws: An error if the model container cannot be created.
static func makeSharedContext() async throws -> ModelContainer {
try ModelContainer(
for: Todo.self,
configurations: .init(isStoredInMemoryOnly: true)
)
}
/// Applies the empty model container to the preview content.
///
/// This method is called by SwiftUI to apply the modifier to the preview.
/// It injects the empty model container into the SwiftUI environment, making it
/// available to any views that use `@Query` or `@Environment(\.modelContext)`.
/// Queries will return empty results, allowing you to test empty state behavior.
///
/// - Parameters:
/// - content: The preview content to modify.
/// - context: The empty model container.
/// - Returns: The content with the empty 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 an empty model container.
///
/// Use this trait to test views in their empty state without any data.
/// This is particularly useful for testing empty state UI, placeholder content,
/// and ensuring views handle the absence of data gracefully.
///
/// ## Example
/// ```swift
/// #Preview("Empty State", traits: .emptyContainer) {
/// TaskGroupListView()
/// }
/// ```
///
/// The view will receive an empty SwiftData container, causing any `@Query`
/// properties to return empty collections.
static var emptyContainer: Self = .modifier(EmptyContainerModifier())
}