Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AnalysisLevel>latest</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup>
<Authors>Luminous Team</Authors>
<Company>Luminous</Company>
<Product>Luminous Family Hub</Product>
<Copyright>Copyright (c) Luminous Team. All rights reserved.</Copyright>
<RepositoryUrl>https://github.com/trickpatty/Luminous</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>
</Project>
57 changes: 57 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>

<ItemGroup>
<!-- ASP.NET Core -->
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.2.0" />

<!-- Azure SDK -->
<PackageVersion Include="Azure.Identity" Version="1.13.1" />
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.46.1" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.2" />
<PackageVersion Include="Microsoft.Azure.SignalR" Version="1.28.0" />
<PackageVersion Include="Microsoft.Extensions.Azure" Version="1.8.0" />
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.2" />

<!-- Identifiers -->
<PackageVersion Include="Nanoid" Version="3.1.0" />

<!-- MediatR for CQRS -->
<PackageVersion Include="MediatR" Version="12.4.1" />

<!-- FluentValidation -->
<PackageVersion Include="FluentValidation" Version="11.11.0" />
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />

<!-- Authentication -->
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
<PackageVersion Include="Fido2" Version="4.0.0" />
<PackageVersion Include="Fido2.AspNet" Version="4.0.0" />

<!-- Caching -->
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />

<!-- Health Checks -->
<PackageVersion Include="AspNetCore.HealthChecks.CosmosDb" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.Redis" Version="9.0.0" />
<PackageVersion Include="AspNetCore.HealthChecks.AzureServiceBus" Version="9.0.0" />

<!-- Logging -->
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />

<!-- Testing -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
<PackageVersion Include="Bogus" Version="35.6.1" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>
</Project>
92 changes: 92 additions & 0 deletions Luminous.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1

# Source Projects
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Domain", "src\Luminous.Domain\Luminous.Domain.csproj", "{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Application", "src\Luminous.Application\Luminous.Application.csproj", "{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Infrastructure", "src\Luminous.Infrastructure\Luminous.Infrastructure.csproj", "{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Api", "src\Luminous.Api\Luminous.Api.csproj", "{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Shared", "src\Luminous.Shared\Luminous.Shared.csproj", "{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}"
EndProject

# Test Projects
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Domain.Tests", "tests\Luminous.Domain.Tests\Luminous.Domain.Tests.csproj", "{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Application.Tests", "tests\Luminous.Application.Tests\Luminous.Application.Tests.csproj", "{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Api.Tests", "tests\Luminous.Api.Tests\Luminous.Api.Tests.csproj", "{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Integration.Tests", "tests\Luminous.Integration.Tests\Luminous.Integration.Tests.csproj", "{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}"
EndProject

# Solution Folders
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{10000000-0000-0000-0000-000000000001}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{20000000-0000-0000-0000-000000000002}"
EndProject

Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.Build.0 = Release|Any CPU
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.Build.0 = Release|Any CPU
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.Build.0 = Release|Any CPU
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.Build.0 = Release|Any CPU
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Release|Any CPU.Build.0 = Release|Any CPU
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Release|Any CPU.Build.0 = Release|Any CPU
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Release|Any CPU.Build.0 = Release|Any CPU
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D} = {10000000-0000-0000-0000-000000000001}
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E} = {10000000-0000-0000-0000-000000000001}
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F} = {10000000-0000-0000-0000-000000000001}
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A} = {10000000-0000-0000-0000-000000000001}
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B} = {10000000-0000-0000-0000-000000000001}
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C} = {20000000-0000-0000-0000-000000000002}
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D} = {20000000-0000-0000-0000-000000000002}
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E} = {20000000-0000-0000-0000-000000000002}
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F} = {20000000-0000-0000-0000-000000000002}
EndGlobalSection
EndGlobal
11 changes: 7 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Luminous Architecture Document

> **Document Version:** 2.0.0
> **Document Version:** 2.1.0
> **Last Updated:** 2025-12-21
> **Status:** Draft
> **TOGAF Phase:** Phase B-D (Architecture Development)
Expand Down Expand Up @@ -259,9 +259,10 @@ LUMINOUS FAMILY HUB (MULTI-TENANT)
#### Family (Tenant Root)

```csharp
// Uses NanoId for URL-friendly, compact unique identifiers
public class Family
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
public string Name { get; set; } = string.Empty;
public string Timezone { get; set; } = "UTC";
public FamilySettings Settings { get; set; } = new();
Expand All @@ -284,7 +285,7 @@ public class FamilySettings
```csharp
public class User
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
public string FamilyId { get; set; } = string.Empty; // Partition key
public string ExternalId { get; set; } = string.Empty; // Internal auth ID
public string Email { get; set; } = string.Empty;
Expand All @@ -311,7 +312,7 @@ public enum UserRole
```csharp
public class Device
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
public string FamilyId { get; set; } = string.Empty; // Partition key
public DeviceType Type { get; set; } = DeviceType.Display;
public string Name { get; set; } = string.Empty;
Expand Down Expand Up @@ -422,6 +423,7 @@ luminous/
| **Real-time** | Azure SignalR Service | Latest | WebSocket at scale |
| **Identity** | In-house (FIDO2/WebAuthn) | Latest | Passwordless-first auth |
| **IaC** | Bicep + AVMs | Latest | Azure-native, verified modules |
| **Identifiers** | NanoId | 3.1.0 | URL-friendly, compact unique IDs |

### Platform Matrix

Expand Down Expand Up @@ -724,3 +726,4 @@ services:
|---------|------|--------|---------|
| 1.0.0 | 2025-12-21 | Luminous Team | Initial architecture document |
| 2.0.0 | 2025-12-21 | Luminous Team | Updated for Azure/.NET/Angular stack, multi-tenancy |
| 2.1.0 | 2025-12-21 | Luminous Team | Migrate from Guid to NanoId for unique identifiers |
34 changes: 24 additions & 10 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Luminous Development Roadmap

> **Document Version:** 2.1.0
> **Document Version:** 2.2.0
> **Last Updated:** 2025-12-21
> **Status:** Active
> **TOGAF Phase:** Phase E/F (Opportunities, Solutions & Migration Planning)
Expand Down Expand Up @@ -102,7 +102,7 @@ Phase 6: Intelligence & Ecosystem

| Phase | Name | Focus | Key Deliverables | Status |
|-------|------|-------|------------------|--------|
| **0** | Foundation | Infrastructure | Azure IaC, .NET solution, Angular shell, Passwordless Auth | 🟡 In Progress (0.1 Complete) |
| **0** | Foundation | Infrastructure | Azure IaC, .NET solution, Angular shell, Passwordless Auth | 🟡 In Progress (0.1, 0.2 Complete) |
| **1** | Core Platform | Multi-tenancy | Family sign-up, device linking, CosmosDB, web MVP | ⬜ Not Started |
| **2** | Display & Calendar | Calendar visibility | Display app, calendar integration, SignalR sync | ⬜ Not Started |
| **3** | Native Mobile | Mobile apps | iOS (Swift), Android (Kotlin), push notifications | ⬜ Not Started |
Expand Down Expand Up @@ -147,15 +147,28 @@ Establish the Azure infrastructure, .NET backend, Angular frontend, and developm
- [x] Redis Cache for session management
- [x] Log Analytics and Application Insights for monitoring

#### 0.2 .NET Solution Structure
#### 0.2 .NET Solution Structure ✅ COMPLETED

- [x] **0.2.1** Create solution with Clean Architecture layers
- *Implemented: Luminous.sln with Directory.Build.props, Directory.Packages.props for centralized package management*
- [x] **0.2.2** Set up Luminous.Domain with entities and value objects
- *Implemented: 10+ entities (Family, User, Device, Event, Chore, Routine, etc.), 8+ value objects, repository interfaces, domain events*
- [x] **0.2.3** Set up Luminous.Application with CQRS handlers
- *Implemented: MediatR-based CQRS with commands/queries, FluentValidation validators, pipeline behaviors*
- [x] **0.2.4** Set up Luminous.Infrastructure with CosmosDB repositories
- *Implemented: CosmosDbContext, base repository pattern, concrete repositories for all entities, Unit of Work*
- [x] **0.2.5** Set up Luminous.Api with controllers and middleware
- *Implemented: ASP.NET Core API with controllers, exception handling middleware, Swagger/OpenAPI*
- [x] **0.2.6** Configure dependency injection and options pattern
- *Implemented: DependencyInjection.cs in each layer, options pattern for CosmosDB settings*
- [x] **0.2.7** Set up xUnit test projects
- *Implemented: 4 test projects (Domain.Tests, Application.Tests, Api.Tests, Integration.Tests) with sample tests*

- [ ] **0.2.1** Create solution with Clean Architecture layers
- [ ] **0.2.2** Set up Luminous.Domain with entities and value objects
- [ ] **0.2.3** Set up Luminous.Application with CQRS handlers
- [ ] **0.2.4** Set up Luminous.Infrastructure with CosmosDB repositories
- [ ] **0.2.5** Set up Luminous.Api with controllers and middleware
- [ ] **0.2.6** Configure dependency injection and options pattern
- [ ] **0.2.7** Set up xUnit test projects
**Additional deliverables:**
- [x] Luminous.Shared project for shared DTOs and contracts
- [x] Centralized package version management (Directory.Packages.props)
- [x] Global.json for SDK version pinning
- [x] Sample unit tests demonstrating testing patterns

#### 0.3 Angular Web Application

Expand Down Expand Up @@ -630,3 +643,4 @@ These can be developed in parallel after Phase 0:
| 2.0.0 | 2025-12-21 | Luminous Team | Updated for Azure/.NET/Angular stack |
| 2.1.0 | 2025-12-21 | Luminous Team | Phase 0.1 Azure Infrastructure completed |
| 2.1.1 | 2025-12-21 | Luminous Team | Refactored to use AVMs directly from public registry |
| 2.2.0 | 2025-12-21 | Luminous Team | Phase 0.2 .NET Solution Structure completed |
6 changes: 6 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"sdk": {
"version": "9.0.100",
"rollForward": "latestMinor"
}
}
46 changes: 46 additions & 0 deletions src/Luminous.Api/Controllers/ApiControllerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Luminous.Shared.Contracts;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace Luminous.Api.Controllers;

/// <summary>
/// Base controller with common functionality.
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public abstract class ApiControllerBase : ControllerBase
{
private ISender? _mediator;

/// <summary>
/// Gets the MediatR sender.
/// </summary>
protected ISender Mediator => _mediator ??=
HttpContext.RequestServices.GetRequiredService<ISender>();

/// <summary>
/// Creates an OK response with data.
/// </summary>
protected ActionResult<ApiResponse<T>> OkResponse<T>(T data)
{
return Ok(ApiResponse<T>.Ok(data));
}

/// <summary>
/// Creates a Created response with data.
/// </summary>
protected ActionResult<ApiResponse<T>> CreatedResponse<T>(string location, T data)
{
return Created(location, ApiResponse<T>.Ok(data));
}

/// <summary>
/// Creates a No Content response.
/// </summary>
protected new ActionResult NoContent()
{
return base.NoContent();
}
}
38 changes: 38 additions & 0 deletions src/Luminous.Api/Controllers/ChoresController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Luminous.Application.DTOs;
using Luminous.Application.Features.Chores.Queries;
using Luminous.Shared.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Luminous.Api.Controllers;

/// <summary>
/// Controller for chore management.
/// </summary>
[Authorize]
public class ChoresController : ApiControllerBase
{
/// <summary>
/// Gets chores for a family.
/// </summary>
/// <param name="familyId">The family ID.</param>
/// <param name="assigneeId">Optional assignee filter.</param>
/// <param name="includeInactive">Whether to include inactive chores.</param>
/// <returns>The list of chores.</returns>
[HttpGet("family/{familyId}")]
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ChoreDto>>), StatusCodes.Status200OK)]
public async Task<ActionResult<ApiResponse<IReadOnlyList<ChoreDto>>>> GetChores(
string familyId,
[FromQuery] string? assigneeId = null,
[FromQuery] bool includeInactive = false)
{
var query = new GetChoresQuery
{
FamilyId = familyId,
AssigneeId = assigneeId,
IncludeInactive = includeInactive
};
var result = await Mediator.Send(query);
return OkResponse(result);
}
}
Loading