93 lines
4.0 KiB
C#
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);
|
|
}
|
|
}
|