using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Crew.SearchMember; internal sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.Keyword) || request.Keyword.Trim().Length < 2) { return new Response([]); } var kw = request.Keyword.Trim(); // 이미 등록된 크루원의 MemberID 목록 var existingMemberIDs = await db.CrewMember.AsNoTracking() .Where(m => m.CrewID == request.CrewID) .Select(m => m.MemberID) .ToListAsync(ct); var list = await db.Member.AsNoTracking() .Where(m => !m.IsWithdraw && !m.IsDenied) .Where(m => !existingMemberIDs.Contains(m.ID)) .Where(m => (m.Name != null && m.Name.Contains(kw)) || m.Email.Contains(kw)) .Take(20) .Select(m => new SearchResultItem( m.ID, m.Name, m.Email, m.Thumb, db.Channel.AsNoTracking() .Where(c => c.MemberID == m.ID) .Select(c => c.Name) .FirstOrDefault() )) .ToListAsync(ct); return new Response(list); } }