using System.Security.Claims; using FastEndpoints; using FluentValidation; using Microsoft.EntityFrameworkCore; using TrackQrApi.Data; using TrackQrApi.Features.Auth.Common; using TrackQrApi.Features.Projects.Common; namespace TrackQrApi.Features.Projects.Endpoints; public class UpdateProjectRequest { public Guid WorkspaceId { get; set; } public Guid Id { get; set; } public string Name { get; set; } = string.Empty; public string? Description { get; set; } } public class UpdateProjectValidator : Validator { public UpdateProjectValidator() { RuleFor(x => x.Name) .NotEmpty().WithMessage("Name is required") .MaximumLength(100).WithMessage("Name must not exceed 100 characters"); } } public class UpdateProjectEndpoint(AppDbContext db) : Endpoint { public override void Configure() { Put("/workspaces/{WorkspaceId}/projects/{Id}"); } public override async Task HandleAsync(UpdateProjectRequest req, CancellationToken ct) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!); var project = await db.Projects .Include(p => p.Workspace) .Include(p => p.ShortLinks) .Include(p => p.QRCodeDesigns) .FirstOrDefaultAsync( p => p.Id == req.Id && p.WorkspaceId == req.WorkspaceId && p.Workspace.OwnerUserId == userId, ct); if (project is null) { await HttpContext.Response.SendAsync(new MessageResponse("Project not found"), 404, cancellation: ct); return; } project.Name = req.Name; project.Description = req.Description; await db.SaveChangesAsync(ct); var response = new ProjectResponse( project.Id, project.WorkspaceId, project.Name, project.Description, project.ShortLinks.Count(l => l.DeletedAt == null), project.QRCodeDesigns.Count, project.CreatedAt ); await HttpContext.Response.SendAsync(response, cancellation: ct); } }