using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Member.List.Search; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.Member.AsNoTracking().Include(x => x.MemberGrade).Include(x => x.MemberStats).AsQueryable(); // 키워드 검색 if (!string.IsNullOrWhiteSpace(request.Keyword)) { query = request.Search switch { 1 => query.Where(x => x.ID.ToString().Contains(request.Keyword)), 2 => query.Where(x => x.Email.Contains(request.Keyword)), 3 => query.Where(x => x.Name != null && x.Name.Contains(request.Keyword)), 4 => query.Where(x => x.FullName != null && x.FullName.Contains(request.Keyword)), 5 => query.Where(x => x.Phone != null && x.Phone.Contains(request.Keyword)), _ => query }; } // 날짜 필터 if (!string.IsNullOrWhiteSpace(request.StartAt) && DateTime.TryParse(request.StartAt, out var startAt)) { query = query.Where(x => x.CreatedAt >= startAt); } if (!string.IsNullOrWhiteSpace(request.EndAt) && DateTime.TryParse(request.EndAt, out var endAt)) { query = query.Where(x => x.CreatedAt <= endAt); } // 성별 필터 if (request.Gender.HasValue) { query = query.Where(x => x.Gender == request.Gender.Value); } // 이메일 인증 필터 if (request.IsEmailVerified == 1) { query = query.Where(x => x.IsEmailVerified); } // 본인 인증 필터 if (request.IsAuthCertified == 1) { query = query.Where(x => x.IsAuthCertified); } var counts = await query.GroupBy(c => 1).Select(c => new Response.TabCounts { All = c.Count(), Denied = c.Count(x => x.IsDenied), Withdraw = c.Count(x => x.IsWithdraw), Admin = c.Count(x => x.IsAdmin) }).FirstOrDefaultAsync(ct) ?? new Response.TabCounts(); query = request.Tab switch { 1 => query.Where(x => x.IsDenied), 2 => query.Where(x => x.IsWithdraw), 3 => query.Where(x => x.IsAdmin), _ => query }; var total = await query.CountAsync(ct); var skip = (request.PageNum - 1) * request.PerPage; var list = await query .OrderByDescending(x => x.ID) .Skip(skip) .Take(request.PerPage) .Select(x => new { x.ID, x.Email, x.Name, x.FullName, x.Icon, x.Phone, x.Birthday, x.Gender, GradeName = x.MemberGrade != null ? x.MemberGrade.KorName : null, x.IsEmailVerified, x.IsAuthCertified, x.IsDenied, x.IsWithdraw, Following = x.MemberStats != null ? x.MemberStats.FollowingCount : 0, Followed = x.MemberStats != null ? x.MemberStats.FollowerCount : 0, x.LastLoginAt, x.LastLoginIp, x.CreatedAt, x.UpdatedAt }) .ToListAsync(ct); var rows = list.Select((x, idx) => new Response.Row { Num = total - skip - idx, ID = x.ID, Email = x.Email, Name = x.Name, FullName = x.FullName, Icon = x.Icon, Phone = x.Phone, Birthday = x.Birthday?.ToString("yyyy-MM-dd"), Gender = x.Gender switch { Domain.Entities.Members.ValueObject.Gender.Male => "남자", Domain.Entities.Members.ValueObject.Gender.Female => "여자", _ => null }, GradeName = x.GradeName, IsEmailVerified = x.IsEmailVerified, IsAuthCertified = x.IsAuthCertified, IsDenied = x.IsDenied, IsWithdraw = x.IsWithdraw, Following = x.Following, Followed = x.Followed, LastLoginAt = x.LastLoginAt, LastLoginIp = x.LastLoginIp, CreatedAt = x.CreatedAt, UpdatedAt = x.UpdatedAt }).ToList(); return new Response { Total = total, Counts = counts, List = rows }; } }