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
8 changes: 8 additions & 0 deletions src/Medications.Api/Contracts/CreateMedicationRequest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
using System.ComponentModel.DataAnnotations;

namespace Medications.Api.Contracts;

public class CreateMedicationRequest
{

[Required(AllowEmptyStrings = false)]
public required string Name { get; set; }

[Range(1, int.MaxValue, ErrorMessage = "Quantity must be greater than 0")]
public int Quantity { get; set; }
}
6 changes: 0 additions & 6 deletions src/Medications.Api/Contracts/CreateMedicationResponse.cs

This file was deleted.

3 changes: 3 additions & 0 deletions src/Medications.Api/Contracts/MedicationResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Medications.Api.Contracts;

public sealed record MedicationResponse(int Id, string Name, int Quantity, DateTimeOffset CreationDate);
3 changes: 2 additions & 1 deletion src/Medications.Api/Data/MedicationsDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

namespace Medications.Api.Data;

public class MedicationsDbContext(DbContextOptions<MedicationsDbContext> options) : DbContext(options)
public class MedicationsDbContext(
DbContextOptions<MedicationsDbContext> options) : DbContext(options)
{
public DbSet<Medication> Medications => Set<Medication>();
}
42 changes: 35 additions & 7 deletions src/Medications.Api/Endpoints/MedicationEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using Medications.Api.Contracts;
using Medications.Api.Data;
using Medications.Api.Entities;
using Medications.Api.Mapping;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;

namespace Medications.Api.Endpoints;

public static class MedicationEndpoints
{
public static void MapMedicationEndpoints(this WebApplication app)
public static IEndpointRouteBuilder MapMedicationEndpoints(this IEndpointRouteBuilder endpoints)
{
var group = app.MapGroup("/api/medications")
var group = endpoints.MapGroup("/api/medications")
.WithTags("Medications");

group.MapGet("/", GetAllMedications)
Expand All @@ -19,20 +20,47 @@ public static void MapMedicationEndpoints(this WebApplication app)
group.MapGet("/{id}", GetMedication)
.WithName("GetMedication")
.WithDescription("Retrieve a specific medication by its ID.");

group.MapPost("/", CreateMedication)
.WithName("CreateMedication")
.WithDescription("Create a new medication");

return endpoints;
}

private static async Task<Ok<List<Medication>>> GetAllMedications(MedicationsDbContext dbContext)
private static async Task<Ok<List<MedicationResponse>>> GetAllMedications(MedicationsDbContext dbContext)
{
var medications = await dbContext.Medications.ToListAsync();
return TypedResults.Ok(medications);

var medicationResponseList = medications.Select(medication => medication.ToResponse()).ToList();

return TypedResults.Ok(medicationResponseList);
}

private static async Task<Results<Ok<Medication>, NotFound>> GetMedication(int id, MedicationsDbContext dbContext)
private static async Task<Results<Ok<MedicationResponse>, NotFound>> GetMedication(
int id, MedicationsDbContext dbContext)
{
var medication = await dbContext.Medications.FindAsync(id);

if (medication is null) return TypedResults.NotFound();

return TypedResults.Ok(medication);
return TypedResults.Ok(medication.ToResponse());
}

private static async Task<CreatedAtRoute<MedicationResponse>> CreateMedication(
CreateMedicationRequest request,
MedicationsDbContext dbContext,
TimeProvider timeProvider,
CancellationToken cancellationToken)
{
var medication = request.ToMedication(timeProvider);

dbContext.Add(medication);

await dbContext.SaveChangesAsync(cancellationToken);

var medicationResponse = medication.ToResponse();

return TypedResults.CreatedAtRoute(medicationResponse, "GetMedication", new { id = medicationResponse.Id });
}
}
26 changes: 26 additions & 0 deletions src/Medications.Api/Mapping/MedicationMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Medications.Api.Contracts;
using Medications.Api.Entities;

namespace Medications.Api.Mapping;

public static class MedicationMapping
{
public static Medication ToMedication(this CreateMedicationRequest request, TimeProvider timeProvider)
{
return new Medication
{
Name = request.Name.Trim(),
Quantity = request.Quantity,
CreationDate = timeProvider.GetUtcNow()
};
}

public static MedicationResponse ToResponse(this Medication medication)
{
return new MedicationResponse(
medication.Id,
medication.Name,
medication.Quantity,
medication.CreationDate);
}
}
3 changes: 3 additions & 0 deletions src/Medications.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MedicationsDbContext>(opt => opt.UseInMemoryDatabase("Medications"));
builder.Services.AddOpenApi();
builder.Services.AddValidation();
builder.Services.AddSingleton(TimeProvider.System);

var app = builder.Build();

if (app.Environment.IsDevelopment())
Expand Down