using TestAspNetCore.Infra; using TestAspNetCore.Utils; namespace TestAspNetCore.Core.Jobs; public static class JobApi { public const string Prefix = "/api/jobs"; public static void MapEndpoints(IEndpointRouteBuilder endpoints) { var group = endpoints.MapGroup(Prefix) .WithTags("Jobs"); group.MapPost("/", CreateJobEndpoint.Handle) .WithSummary("Create a job") .WithRequestValidation(); group.MapGet("/", GetJobListEndpoint.Handle) .WithSummary("Get job list"); group.MapGet("/{id}", GetJobEndpoint.Handle) .WithSummary("Get job by id"); group.MapPut("/{id}", UpdateJobEndpoint.Handle) .WithSummary("Update job by id") .WithRequestValidation(); group.MapDelete("/{id}", DeleteJobEndpoint.Handle) .WithSummary("Delete job by id"); } } public static class CreateJobEndpoint { public record Request( string ClientName, string Pickup, string Dropoff ); public record Response(int Id); public class RequestValidator : AbstractValidator { public RequestValidator() { RuleFor(x => x.ClientName).NotEmpty().MaximumLength(250); RuleFor(x => x.Pickup).NotEmpty().MaximumLength(120); RuleFor(x => x.Dropoff).NotEmpty().MaximumLength(120); } } public static async Task> Handle(Request request, AppDbContext db, CancellationToken ct) { var row = new Job { ClientName = request.ClientName, Pickup = request.Pickup, Dropoff = request.Dropoff, }; await db.Jobs.AddAsync(row, ct); await db.SaveChangesAsync(ct); var response = new Response(row.Id); return TypedResults.Ok(response); } } public static class GetJobListEndpoint { public static async Task> Handle(AppDbContext db, CancellationToken ct) { var results = await db.Jobs.ToArrayAsync(ct); return TypedResults.Ok(results); } } public static class GetJobEndpoint { public static async Task, NotFound>> Handle( int id, AppDbContext db, CancellationToken ct) { var result = await db.Jobs .Where(x => x.Id == id) .SingleOrDefaultAsync(ct); return result is null ? TypedResults.NotFound() : TypedResults.Ok(result); } } public static class UpdateJobEndpoint { public record Request( string ClientName, string Pickup, string Dropoff ); public class RequestValidator : AbstractValidator { public RequestValidator() { RuleFor(x => x.ClientName).NotEmpty().MaximumLength(250); RuleFor(x => x.Pickup).NotEmpty().MaximumLength(120); RuleFor(x => x.Dropoff).NotEmpty().MaximumLength(120); } } public static async Task> Handle( int id, Request request, AppDbContext db, CancellationToken ct) { var result = await db.Jobs .Where(x => x.Id == id) .SingleOrDefaultAsync(ct); if (result == null) { return TypedResults.NotFound(); } result.ClientName = request.ClientName; result.Pickup = request.Pickup; result.Dropoff = request.Dropoff; result.LastUpdatedAtUtc = DateTime.UtcNow; await db.SaveChangesAsync(ct); return TypedResults.Ok(); } } public static class DeleteJobEndpoint { public static async Task> Handle( int id, AppDbContext db, CancellationToken ct) { var rowsDeleted = await db.Jobs .Where(x => x.Id == id) .ExecuteDeleteAsync(ct); return rowsDeleted == 1 ? TypedResults.Ok() : TypedResults.NotFound(); } }