Files
Nexus.Reader/src/NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs
T

93 lines
4.0 KiB
C#

using MediatR;
using FluentResults;
using Microsoft.EntityFrameworkCore;
using NexusReader.Application.DTOs.User;
using NexusReader.Data.Persistence;
namespace NexusReader.Application.Queries.User;
public class GetUserProfileQueryHandler : IRequestHandler<GetUserProfileQuery, Result<UserProfileDto>>
{
private readonly IDbContextFactory<AppDbContext> _dbContextFactory;
public GetUserProfileQueryHandler(IDbContextFactory<AppDbContext> dbContextFactory)
{
_dbContextFactory = dbContextFactory;
}
public async Task<Result<UserProfileDto>> Handle(GetUserProfileQuery request, CancellationToken cancellationToken)
{
using var dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
var profile = await dbContext.Users
.Where(u => u.Id == request.UserId)
.Select(u => new UserProfileDto
{
Email = u.Email ?? string.Empty,
UserId = u.Id,
AITokensUsed = u.AITokensUsed,
TenantId = u.TenantId != null && u.TenantId.Length == 36 ? new Guid(u.TenantId) : Guid.Empty,
Plan = u.SubscriptionPlan != null ? new SubscriptionPlanDto
{
Id = u.SubscriptionPlan.Id,
Name = u.SubscriptionPlan.PlanName,
AITokenLimit = u.SubscriptionPlan.AITokenLimit,
MonthlyPrice = u.SubscriptionPlan.MonthlyPrice
} : new SubscriptionPlanDto(),
AverageQuizScore = u.QuizResults.Any(q => q.TotalQuestions > 0)
? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)
: 0,
DisplayName = u.DisplayName,
BooksReadCount = u.Ebooks.Count(),
ConceptsMappedCount = dbContext.KnowledgeUnits.Count(k => k.TenantId == u.TenantId || k.TenantId == "global" || string.IsNullOrEmpty(k.TenantId)),
LastReadBook = u.Ebooks.OrderByDescending(e => e.LastReadDate).Select(e => new LastReadBookDto
{
Id = e.Id,
Title = e.Title,
Author = new AuthorDto
{
Id = e.Author.Id,
Name = e.Author.Name
},
CoverUrl = e.CoverUrl,
Progress = e.Progress,
LastChapter = e.LastChapter ?? "Rozpoczynanie...",
LastChapterIndex = e.LastChapterIndex,
Description = e.Description,
IsReadyForReading = e.IsReadyForReading
}).FirstOrDefault(),
RecentQuizzes = u.QuizResults.OrderByDescending(q => q.CompletedDate).Take(5).Select(q => new QuizResultDto
{
Id = q.Id,
Topic = q.Topic,
Score = q.Score,
TotalQuestions = q.TotalQuestions,
Percentage = q.Percentage,
CompletedDate = q.CompletedDate
}).ToList(),
MappedConcepts = dbContext.KnowledgeUnits
.Where(k => k.TenantId == u.TenantId || k.TenantId == "global" || string.IsNullOrEmpty(k.TenantId))
.OrderByDescending(k => k.CreatedAt)
.Take(6)
.Select(k => new MappedConceptDto
{
Id = k.Id,
Type = k.Type.ToString(),
Content = k.Content
})
.ToList(),
Roles = dbContext.UserRoles
.Where(ur => ur.UserId == u.Id)
.Join(dbContext.Roles, ur => ur.RoleId, r => r.Id, (ur, r) => r.Name!)
.ToArray()
})
.FirstOrDefaultAsync(cancellationToken);
if (profile == null)
{
return Result.Fail("Profile not found.");
}
return Result.Ok(profile);
}
}