using FluentValidation; using FluentValidation.Results; using Microsoft.EntityFrameworkCore; using Vegasco.Server.Api.Authentication; using Vegasco.Server.Api.Common; using Vegasco.Server.Api.Persistence; using Vegasco.Server.Api.Users; namespace Vegasco.Server.Api.Cars; public static class CreateCar { public record Request(string Name); public record Response(Guid Id, string Name); public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) { return builder .MapPost("cars", Endpoint) .WithTags("Cars") .WithDescription("Creates a new car") .Produces(201) .ProducesValidationProblem() .Produces(409); } public class Validator : AbstractValidator { public Validator() { RuleFor(x => x.Name) .NotEmpty() .MaximumLength(CarTableConfiguration.NameMaxLength); } } public static async Task Endpoint( Request request, IEnumerable> validators, ApplicationDbContext dbContext, UserAccessor userAccessor, CancellationToken cancellationToken) { List failedValidations = await validators.ValidateAllAsync(request, cancellationToken: cancellationToken); if (failedValidations.Count > 0) { return TypedResults.BadRequest(new HttpValidationProblemDetails(failedValidations.ToCombinedDictionary())); } string userId = userAccessor.GetUserId(); User? user = await dbContext.Users.FindAsync([userId], cancellationToken: cancellationToken); if (user is null) { user = new User { Id = userId }; await dbContext.Users.AddAsync(user, cancellationToken); } Car car = new() { Name = request.Name.Trim(), UserId = userId }; bool isDuplicate = await dbContext.Cars .AnyAsync(x => x.Name.ToUpper() == request.Name.ToUpper(), cancellationToken); if (isDuplicate) { return TypedResults.Conflict(); } await dbContext.Cars.AddAsync(car, cancellationToken); await dbContext.SaveChangesAsync(cancellationToken); Response response = new(car.Id.Value, car.Name); return TypedResults.Created($"/v1/cars/{car.Id}", response); } }