using FastEndpoints; using MetaCourse.Api.Data; using MetaCourse.Api.DTOs.Progress; using Microsoft.EntityFrameworkCore; namespace MetaCourse.Api.Endpoints.Progress; public class GetCourseProgressRequest { public Guid CourseId { get; set; } public Guid UserId { get; set; } } public class GetCourseProgressEndpoint(AppDbContext db) : Endpoint { public override void Configure() { Get("api/courses/{courseId}/progress"); AllowAnonymous(); Summary(s => s.Summary = "Retourne la progression d'un utilisateur dans un cours"); } public override async Task HandleAsync(GetCourseProgressRequest req, CancellationToken ct) { var course = await db.Courses .AsNoTracking() .Include(c => c.Topics) .ThenInclude(t => t.TopicResources) .FirstOrDefaultAsync(c => c.Id == req.CourseId, ct); if (course is null) { await SendNotFoundAsync(ct); return; } var topicIds = course.Topics.Select(t => t.Id).ToList(); var resourceIds = course.Topics .SelectMany(t => t.TopicResources.Select(tr => tr.ResourceId)) .Distinct() .ToList(); var completedTopics = await db.UserTopicProgresses .CountAsync(p => p.UserId == req.UserId && topicIds.Contains(p.TopicId) && p.Completed, ct); var completedResources = await db.UserResourceProgresses .CountAsync(p => p.UserId == req.UserId && resourceIds.Contains(p.ResourceId) && p.Completed, ct); var totalTopics = topicIds.Count; var totalResources = resourceIds.Count; var percentage = totalTopics == 0 ? 0 : Math.Round((completedTopics + completedResources) / (double)(totalTopics + totalResources) * 100, 1); await SendOkAsync(new CourseProgressDto { CourseId = req.CourseId, UserId = req.UserId, TotalTopics = totalTopics, CompletedTopics = completedTopics, TotalResources = totalResources, CompletedResources = completedResources, ProgressPercentage = percentage }, ct); } }