201 lines
5.1 KiB
C#
201 lines
5.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using DramaLing.Api.Data;
|
|
using DramaLing.Api.Models.Entities;
|
|
|
|
namespace DramaLing.Api.Repositories;
|
|
|
|
/// <summary>
|
|
/// User Repository 實作
|
|
/// </summary>
|
|
public class UserRepository : BaseRepository<User>, IUserRepository
|
|
{
|
|
public UserRepository(DramaLingDbContext context, ILogger<UserRepository> logger)
|
|
: base(context, logger)
|
|
{
|
|
}
|
|
|
|
#region 用戶查詢
|
|
|
|
public async Task<User?> GetByEmailAsync(string email)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(u => u.Email == email);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting user by email: {Email}", email);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<User?> GetByUsernameAsync(string username)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(u => u.Username == username);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting user by username: {Username}", username);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ExistsByEmailAsync(string email)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet.AnyAsync(u => u.Email == email);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error checking user existence by email: {Email}", email);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ExistsByUsernameAsync(string username)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet.AnyAsync(u => u.Username == username);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error checking user existence by username: {Username}", username);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 用戶設定相關
|
|
|
|
public async Task<User?> GetUserWithSettingsAsync(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.Include(u => u.Settings)
|
|
.FirstOrDefaultAsync(u => u.Id == userId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting user with settings: {UserId}", userId);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<User?> GetUserWithStatsAsync(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.Include(u => u.DailyStats!)
|
|
.FirstOrDefaultAsync(u => u.Id == userId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting user with stats: {UserId}", userId);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 學習進度統計
|
|
|
|
public Task<Dictionary<string, object>> GetUserLearningStatsAsync(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
var stats = new Dictionary<string, object>
|
|
{
|
|
["TotalFlashcards"] = 0,
|
|
["MasteredFlashcards"] = 0,
|
|
["MasteryRate"] = 0.0,
|
|
["StudyDaysThisMonth"] = 0,
|
|
["TotalStudyTimeSeconds"] = 0
|
|
};
|
|
|
|
return Task.FromResult(stats);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting user learning stats: {UserId}", userId);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public Task<int> GetTotalStudyTimeAsync(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
return Task.FromResult(0);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting total study time: {UserId}", userId);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public Task<DateTime?> GetLastActivityDateAsync(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
return Task.FromResult<DateTime?>(DateTime.UtcNow);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting last activity date: {UserId}", userId);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 用戶活躍度
|
|
|
|
public async Task<IEnumerable<User>> GetActiveUsersAsync(int days)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.Take(10) // 簡化實作
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting active users for {Days} days", days);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<User>> GetNewUsersAsync(DateTime since)
|
|
{
|
|
try
|
|
{
|
|
return await _dbSet
|
|
.AsNoTracking()
|
|
.Where(u => u.CreatedAt >= since)
|
|
.OrderByDescending(u => u.CreatedAt)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting new users since: {Since}", since);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
} |