diff --git a/src/backend/src/FoodDiary.API/Features/WeightTracking/AddWeightLogHandler.cs b/src/backend/src/FoodDiary.API/Features/WeightTracking/AddWeightLogHandler.cs new file mode 100644 index 000000000..00d20df58 --- /dev/null +++ b/src/backend/src/FoodDiary.API/Features/WeightTracking/AddWeightLogHandler.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using FoodDiary.API.Features.WeightTracking.Contracts; +using FoodDiary.Domain.WeightTracking; +using FoodDiary.Infrastructure; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; + +namespace FoodDiary.API.Features.WeightTracking; + +public class AddWeightLogHandler(FoodDiaryContext context) +{ + public async Task Handle(WeightLogBody request, CancellationToken cancellationToken) + { + var weightLogExists = await context.WeightLogs.AnyAsync(wl => wl.Date == request.Date, cancellationToken); + + if (weightLogExists) + { + return Results.Problem( + title: "Failed to add weight log", + detail: "Weight log with such date already exists, please choose another date"); + } + + var weightLog = new WeightLog + { + Date = request.Date.GetValueOrDefault(), + Weight = request.Value + }; + + await context.WeightLogs.AddAsync(weightLog, cancellationToken); + await context.SaveChangesAsync(cancellationToken); + return Results.Ok(); + } +} \ No newline at end of file diff --git a/src/backend/src/FoodDiary.API/Features/WeightTracking/Endpoints.cs b/src/backend/src/FoodDiary.API/Features/WeightTracking/Endpoints.cs index 8277fa83f..75c0cec79 100644 --- a/src/backend/src/FoodDiary.API/Features/WeightTracking/Endpoints.cs +++ b/src/backend/src/FoodDiary.API/Features/WeightTracking/Endpoints.cs @@ -3,7 +3,6 @@ using System.Threading; using FoodDiary.API.Features.WeightTracking.Contracts; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; @@ -18,19 +17,22 @@ public static void MapWeightLogs(this IEndpointRouteBuilder app) .RequireAuthorization(Constants.AuthorizationPolicies.GoogleAllowedEmails); weightLogs.MapGet("/", ( - [Required] DateOnly? from, - [Required] DateOnly? to, - [FromServices] GetWeightLogsHandler handler, - CancellationToken cancellationToken) => - handler.Handle( - new GetWeightLogsRequest(from.GetValueOrDefault(), to.GetValueOrDefault()), - cancellationToken)); - - weightLogs.MapPost("/", (WeightLogBody request) => Results.Ok()); + [Required] DateOnly? from, + [Required] DateOnly? to, + [FromServices] GetWeightLogsHandler handler, + CancellationToken cancellationToken) => handler.Handle( + new GetWeightLogsRequest(from.GetValueOrDefault(), to.GetValueOrDefault()), + cancellationToken)); + + weightLogs.MapPost("/", ( + [FromBody] WeightLogBody request, + [FromServices] AddWeightLogHandler handler, + CancellationToken cancellationToken) => handler.Handle(request, cancellationToken)); } - + public static void AddWeightLogs(this IServiceCollection services) { services.AddScoped(); + services.AddScoped(); } } \ No newline at end of file diff --git a/src/backend/src/FoodDiary.API/Features/GetWeightLogsHandler.cs b/src/backend/src/FoodDiary.API/Features/WeightTracking/GetWeightLogsHandler.cs similarity index 90% rename from src/backend/src/FoodDiary.API/Features/GetWeightLogsHandler.cs rename to src/backend/src/FoodDiary.API/Features/WeightTracking/GetWeightLogsHandler.cs index b62ef1bf0..f95867d86 100644 --- a/src/backend/src/FoodDiary.API/Features/GetWeightLogsHandler.cs +++ b/src/backend/src/FoodDiary.API/Features/WeightTracking/GetWeightLogsHandler.cs @@ -1,13 +1,12 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using FoodDiary.API.Features.WeightTracking; using FoodDiary.API.Features.WeightTracking.Contracts; using FoodDiary.Infrastructure; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -namespace FoodDiary.API.Features; +namespace FoodDiary.API.Features.WeightTracking; public class GetWeightLogsHandler(FoodDiaryContext context) { diff --git a/src/backend/src/FoodDiary.API/Features/WeightTracking/Mappings.cs b/src/backend/src/FoodDiary.API/Features/WeightTracking/Mappings.cs index 4c65074b8..52632c092 100644 --- a/src/backend/src/FoodDiary.API/Features/WeightTracking/Mappings.cs +++ b/src/backend/src/FoodDiary.API/Features/WeightTracking/Mappings.cs @@ -6,4 +6,10 @@ namespace FoodDiary.API.Features.WeightTracking; public static class Mappings { public static WeightLogItem ToWeightLogItem(this WeightLog weightLog) => new(weightLog.Date, weightLog.Weight); + + public static WeightLogBody ToWeightLogBody(this WeightLog weightLog) => new() + { + Date = weightLog.Date, + Value = weightLog.Weight + }; } \ No newline at end of file diff --git a/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiContext.cs b/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiContext.cs index 47f196bbe..ed2a5c3a6 100644 --- a/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiContext.cs +++ b/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiContext.cs @@ -1,3 +1,4 @@ +using System.Net; using System.Net.Http.Json; using FoodDiary.API.Features.WeightTracking; using FoodDiary.API.Features.WeightTracking.Contracts; @@ -10,6 +11,7 @@ public class WeightLogsApiContext(FoodDiaryWebApplicationFactory factory, Infras : BaseContext(factory, infrastructure) { private GetWeightLogsResponse? _getWeightLogsResponse; + private HttpResponseMessage? _addWeightLogResponse; public Task Given_existing_weightLogs(params WeightLog[] weightLogs) { @@ -22,6 +24,11 @@ public async Task When_user_gets_weightLogs(string from, string to) .GetFromJsonAsync($"api/weight-logs?from={from}&to={to}"); } + public async Task When_user_adds_weightLog(WeightLog weightLog) + { + _addWeightLogResponse = await ApiClient.PostAsJsonAsync("api/weight-logs", weightLog.ToWeightLogBody()); + } + public Task Then_response_contains_weightLogs(params WeightLog[] items) { _getWeightLogsResponse?.WeightLogs.Should() @@ -29,4 +36,10 @@ public Task Then_response_contains_weightLogs(params WeightLog[] items) .And.HaveSameCount(items); return Task.CompletedTask; } + + public Task Then_weight_is_successfully_saved() + { + _addWeightLogResponse?.StatusCode.Should().Be(HttpStatusCode.OK); + return Task.CompletedTask; + } } \ No newline at end of file diff --git a/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiTests.cs b/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiTests.cs index 1cb74fdc9..cc3eb75ae 100644 --- a/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiTests.cs +++ b/src/backend/tests/FoodDiary.ComponentTests/Scenarios/WeightTracking/WeightLogsApiTests.cs @@ -9,32 +9,33 @@ public class WeightLogsApiTests(FoodDiaryWebApplicationFactory factory, Infrastr protected override WeightLogsApiContext CreateContext( FoodDiaryWebApplicationFactory factory, InfrastructureFixture infrastructure) => new(factory, infrastructure); - + + private static WeightLog[] WeightLogs => + [ + new() { Date = DateOnly.Parse("2024-10-01"), Weight = 75.6m }, + new() { Date = DateOnly.Parse("2024-10-02"), Weight = 76.5m }, + new() { Date = DateOnly.Parse("2024-10-03"), Weight = 76.2m }, + new() { Date = DateOnly.Parse("2024-10-04"), Weight = 75.9m } + ]; + + [Scenario] + public Task I_can_get_weight_logs() => Run( + c => c.Given_authenticated_user(), + c => c.Given_existing_weightLogs(WeightLogs), + c => c.When_user_gets_weightLogs("2024-10-02", "2024-10-03"), + c => c.Then_response_contains_weightLogs(WeightLogs[2], WeightLogs[1])); + [Scenario] - public Task I_can_get_weight_logs() + public Task I_can_log_my_weight() { - var weightLogs = new WeightLog[] - { - new() { Date = DateOnly.Parse("2024-10-01"), Weight = 75.6m }, - new() { Date = DateOnly.Parse("2024-10-02"), Weight = 76.5m }, - new() { Date = DateOnly.Parse("2024-10-03"), Weight = 76.2m }, - new() { Date = DateOnly.Parse("2024-10-04"), Weight = 75.9m } - }; + var newWeightLog = new WeightLog { Date = DateOnly.Parse("2024-10-05"), Weight = 76.3m }; return Run( c => c.Given_authenticated_user(), - c => c.Given_existing_weightLogs(weightLogs), - c => c.When_user_gets_weightLogs("2024-10-02", "2024-10-03"), - c => c.Then_response_contains_weightLogs(weightLogs[2], weightLogs[1])); + c => c.Given_existing_weightLogs(WeightLogs), + c => c.When_user_adds_weightLog(newWeightLog), + c => c.Then_weight_is_successfully_saved(), + c => c.When_user_gets_weightLogs("2024-10-03", "2024-10-05"), + c => c.Then_response_contains_weightLogs(newWeightLog, WeightLogs[3], WeightLogs[2])); } - - // [Scenario] - // public Task I_can_add_weight_log() - // { - // return Run( - // c => c.When_user_adds_weight_log(), - // c => c.Then_weight_log_is_successfully_created(), - // c => c.When_user_gets_weight_logs(), - // c => c.Then_weight_logs_list_contains([])); - // } } \ No newline at end of file