Skip to content

Commit 687d29f

Browse files
🏗️ arch: implement Phase 0.2 .NET solution structure (#4)
1 parent 3c0c5c7 commit 687d29f

110 files changed

Lines changed: 6561 additions & 14 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Directory.Build.props

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project>
2+
<PropertyGroup>
3+
<TargetFramework>net9.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
7+
<AnalysisLevel>latest</AnalysisLevel>
8+
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
9+
<LangVersion>latest</LangVersion>
10+
</PropertyGroup>
11+
12+
<PropertyGroup>
13+
<Authors>Luminous Team</Authors>
14+
<Company>Luminous</Company>
15+
<Product>Luminous Family Hub</Product>
16+
<Copyright>Copyright (c) Luminous Team. All rights reserved.</Copyright>
17+
<RepositoryUrl>https://github.com/trickpatty/Luminous</RepositoryUrl>
18+
<RepositoryType>git</RepositoryType>
19+
</PropertyGroup>
20+
21+
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
22+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
23+
<NoWarn>$(NoWarn);CS1591</NoWarn>
24+
</PropertyGroup>
25+
</Project>

Directory.Packages.props

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
6+
<ItemGroup>
7+
<!-- ASP.NET Core -->
8+
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
9+
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.2.0" />
10+
11+
<!-- Azure SDK -->
12+
<PackageVersion Include="Azure.Identity" Version="1.13.1" />
13+
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.46.1" />
14+
<PackageVersion Include="Azure.Storage.Blobs" Version="12.23.0" />
15+
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.2" />
16+
<PackageVersion Include="Microsoft.Azure.SignalR" Version="1.28.0" />
17+
<PackageVersion Include="Microsoft.Extensions.Azure" Version="1.8.0" />
18+
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.2" />
19+
20+
<!-- Identifiers -->
21+
<PackageVersion Include="Nanoid" Version="3.1.0" />
22+
23+
<!-- MediatR for CQRS -->
24+
<PackageVersion Include="MediatR" Version="12.4.1" />
25+
26+
<!-- FluentValidation -->
27+
<PackageVersion Include="FluentValidation" Version="11.11.0" />
28+
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
29+
30+
<!-- Authentication -->
31+
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
32+
<PackageVersion Include="Fido2" Version="4.0.0" />
33+
<PackageVersion Include="Fido2.AspNet" Version="4.0.0" />
34+
35+
<!-- Caching -->
36+
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
37+
38+
<!-- Health Checks -->
39+
<PackageVersion Include="AspNetCore.HealthChecks.CosmosDb" Version="9.0.0" />
40+
<PackageVersion Include="AspNetCore.HealthChecks.Redis" Version="9.0.0" />
41+
<PackageVersion Include="AspNetCore.HealthChecks.AzureServiceBus" Version="9.0.0" />
42+
43+
<!-- Logging -->
44+
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
45+
<PackageVersion Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
46+
47+
<!-- Testing -->
48+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
49+
<PackageVersion Include="xunit" Version="2.9.2" />
50+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.0" />
51+
<PackageVersion Include="Moq" Version="4.20.72" />
52+
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
53+
<PackageVersion Include="Bogus" Version="35.6.1" />
54+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
55+
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
56+
</ItemGroup>
57+
</Project>

Luminous.sln

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
7+
# Source Projects
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Domain", "src\Luminous.Domain\Luminous.Domain.csproj", "{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Application", "src\Luminous.Application\Luminous.Application.csproj", "{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Infrastructure", "src\Luminous.Infrastructure\Luminous.Infrastructure.csproj", "{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}"
13+
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Api", "src\Luminous.Api\Luminous.Api.csproj", "{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}"
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Shared", "src\Luminous.Shared\Luminous.Shared.csproj", "{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}"
17+
EndProject
18+
19+
# Test Projects
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Domain.Tests", "tests\Luminous.Domain.Tests\Luminous.Domain.Tests.csproj", "{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}"
21+
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Application.Tests", "tests\Luminous.Application.Tests\Luminous.Application.Tests.csproj", "{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}"
23+
EndProject
24+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Api.Tests", "tests\Luminous.Api.Tests\Luminous.Api.Tests.csproj", "{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}"
25+
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luminous.Integration.Tests", "tests\Luminous.Integration.Tests\Luminous.Integration.Tests.csproj", "{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}"
27+
EndProject
28+
29+
# Solution Folders
30+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{10000000-0000-0000-0000-000000000001}"
31+
EndProject
32+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{20000000-0000-0000-0000-000000000002}"
33+
EndProject
34+
35+
Global
36+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
37+
Debug|Any CPU = Debug|Any CPU
38+
Release|Any CPU = Release|Any CPU
39+
EndGlobalSection
40+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
41+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
43+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
44+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.Build.0 = Release|Any CPU
45+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
47+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
48+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.Build.0 = Release|Any CPU
49+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
51+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
52+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.Build.0 = Release|Any CPU
53+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
55+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
56+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.Build.0 = Release|Any CPU
57+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
59+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
60+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.Build.0 = Release|Any CPU
61+
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62+
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
63+
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
64+
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C}.Release|Any CPU.Build.0 = Release|Any CPU
65+
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66+
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
67+
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
68+
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D}.Release|Any CPU.Build.0 = Release|Any CPU
69+
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
70+
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
71+
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
72+
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E}.Release|Any CPU.Build.0 = Release|Any CPU
73+
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74+
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
75+
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
76+
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.Build.0 = Release|Any CPU
77+
EndGlobalSection
78+
GlobalSection(SolutionProperties) = preSolution
79+
HideSolutionNode = FALSE
80+
EndGlobalSection
81+
GlobalSection(NestedProjects) = preSolution
82+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D} = {10000000-0000-0000-0000-000000000001}
83+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E} = {10000000-0000-0000-0000-000000000001}
84+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F} = {10000000-0000-0000-0000-000000000001}
85+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A} = {10000000-0000-0000-0000-000000000001}
86+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B} = {10000000-0000-0000-0000-000000000001}
87+
{F6A7B8C9-D0E1-9F0A-3B4C-5D6E7F8A9B0C} = {20000000-0000-0000-0000-000000000002}
88+
{A7B8C9D0-E1F2-0A1B-4C5D-6E7F8A9B0C1D} = {20000000-0000-0000-0000-000000000002}
89+
{B8C9D0E1-F2A3-1B2C-5D6E-7F8A9B0C1D2E} = {20000000-0000-0000-0000-000000000002}
90+
{C9D0E1F2-A3B4-2C3D-6E7F-8A9B0C1D2E3F} = {20000000-0000-0000-0000-000000000002}
91+
EndGlobalSection
92+
EndGlobal

docs/ARCHITECTURE.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Luminous Architecture Document
22

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

261261
```csharp
262+
// Uses NanoId for URL-friendly, compact unique identifiers
262263
public class Family
263264
{
264-
public string Id { get; set; } = Guid.NewGuid().ToString();
265+
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
265266
public string Name { get; set; } = string.Empty;
266267
public string Timezone { get; set; } = "UTC";
267268
public FamilySettings Settings { get; set; } = new();
@@ -284,7 +285,7 @@ public class FamilySettings
284285
```csharp
285286
public class User
286287
{
287-
public string Id { get; set; } = Guid.NewGuid().ToString();
288+
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
288289
public string FamilyId { get; set; } = string.Empty; // Partition key
289290
public string ExternalId { get; set; } = string.Empty; // Internal auth ID
290291
public string Email { get; set; } = string.Empty;
@@ -311,7 +312,7 @@ public enum UserRole
311312
```csharp
312313
public class Device
313314
{
314-
public string Id { get; set; } = Guid.NewGuid().ToString();
315+
public string Id { get; set; } = Nanoid.Generate(); // NanoId: compact, URL-safe
315316
public string FamilyId { get; set; } = string.Empty; // Partition key
316317
public DeviceType Type { get; set; } = DeviceType.Display;
317318
public string Name { get; set; } = string.Empty;
@@ -422,6 +423,7 @@ luminous/
422423
| **Real-time** | Azure SignalR Service | Latest | WebSocket at scale |
423424
| **Identity** | In-house (FIDO2/WebAuthn) | Latest | Passwordless-first auth |
424425
| **IaC** | Bicep + AVMs | Latest | Azure-native, verified modules |
426+
| **Identifiers** | NanoId | 3.1.0 | URL-friendly, compact unique IDs |
425427

426428
### Platform Matrix
427429

@@ -724,3 +726,4 @@ services:
724726
|---------|------|--------|---------|
725727
| 1.0.0 | 2025-12-21 | Luminous Team | Initial architecture document |
726728
| 2.0.0 | 2025-12-21 | Luminous Team | Updated for Azure/.NET/Angular stack, multi-tenancy |
729+
| 2.1.0 | 2025-12-21 | Luminous Team | Migrate from Guid to NanoId for unique identifiers |

docs/ROADMAP.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Luminous Development Roadmap
22

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

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

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

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

160173
#### 0.3 Angular Web Application
161174

@@ -630,3 +643,4 @@ These can be developed in parallel after Phase 0:
630643
| 2.0.0 | 2025-12-21 | Luminous Team | Updated for Azure/.NET/Angular stack |
631644
| 2.1.0 | 2025-12-21 | Luminous Team | Phase 0.1 Azure Infrastructure completed |
632645
| 2.1.1 | 2025-12-21 | Luminous Team | Refactored to use AVMs directly from public registry |
646+
| 2.2.0 | 2025-12-21 | Luminous Team | Phase 0.2 .NET Solution Structure completed |

global.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"sdk": {
3+
"version": "9.0.100",
4+
"rollForward": "latestMinor"
5+
}
6+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Luminous.Shared.Contracts;
2+
using MediatR;
3+
using Microsoft.AspNetCore.Mvc;
4+
5+
namespace Luminous.Api.Controllers;
6+
7+
/// <summary>
8+
/// Base controller with common functionality.
9+
/// </summary>
10+
[ApiController]
11+
[Route("api/[controller]")]
12+
[Produces("application/json")]
13+
public abstract class ApiControllerBase : ControllerBase
14+
{
15+
private ISender? _mediator;
16+
17+
/// <summary>
18+
/// Gets the MediatR sender.
19+
/// </summary>
20+
protected ISender Mediator => _mediator ??=
21+
HttpContext.RequestServices.GetRequiredService<ISender>();
22+
23+
/// <summary>
24+
/// Creates an OK response with data.
25+
/// </summary>
26+
protected ActionResult<ApiResponse<T>> OkResponse<T>(T data)
27+
{
28+
return Ok(ApiResponse<T>.Ok(data));
29+
}
30+
31+
/// <summary>
32+
/// Creates a Created response with data.
33+
/// </summary>
34+
protected ActionResult<ApiResponse<T>> CreatedResponse<T>(string location, T data)
35+
{
36+
return Created(location, ApiResponse<T>.Ok(data));
37+
}
38+
39+
/// <summary>
40+
/// Creates a No Content response.
41+
/// </summary>
42+
protected new ActionResult NoContent()
43+
{
44+
return base.NoContent();
45+
}
46+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Luminous.Application.DTOs;
2+
using Luminous.Application.Features.Chores.Queries;
3+
using Luminous.Shared.Contracts;
4+
using Microsoft.AspNetCore.Authorization;
5+
using Microsoft.AspNetCore.Mvc;
6+
7+
namespace Luminous.Api.Controllers;
8+
9+
/// <summary>
10+
/// Controller for chore management.
11+
/// </summary>
12+
[Authorize]
13+
public class ChoresController : ApiControllerBase
14+
{
15+
/// <summary>
16+
/// Gets chores for a family.
17+
/// </summary>
18+
/// <param name="familyId">The family ID.</param>
19+
/// <param name="assigneeId">Optional assignee filter.</param>
20+
/// <param name="includeInactive">Whether to include inactive chores.</param>
21+
/// <returns>The list of chores.</returns>
22+
[HttpGet("family/{familyId}")]
23+
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ChoreDto>>), StatusCodes.Status200OK)]
24+
public async Task<ActionResult<ApiResponse<IReadOnlyList<ChoreDto>>>> GetChores(
25+
string familyId,
26+
[FromQuery] string? assigneeId = null,
27+
[FromQuery] bool includeInactive = false)
28+
{
29+
var query = new GetChoresQuery
30+
{
31+
FamilyId = familyId,
32+
AssigneeId = assigneeId,
33+
IncludeInactive = includeInactive
34+
};
35+
var result = await Mediator.Send(query);
36+
return OkResponse(result);
37+
}
38+
}

0 commit comments

Comments
 (0)