using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Crypto.News.Article.Search { public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.RssNewsArticle.AsNoTracking().Include(x => x.RssFeedSource).AsQueryable(); if (request.RssFeedSourceID.HasValue) { query = query.Where(x => x.RssFeedSourceID == request.RssFeedSourceID.Value); } if (!string.IsNullOrWhiteSpace(request.Keyword)) { var kw = request.Keyword.Trim(); query = query.Where(x => x.Title.Contains(kw) || (x.Description != null && x.Description.Contains(kw))); } var total = await query.CountAsync(ct); var list = await query .OrderByDescending(x => x.PublishedAt ?? x.CreatedAt) .Skip((request.PageNum - 1) * request.PerPage) .Take(request.PerPage) .Select(x => new { x.ID, FeedSourceName = x.RssFeedSource.Name, x.Title, x.Author, x.Link, x.PublishedAt, x.CreatedAt }) .ToListAsync(ct); var startNum = total - ((request.PageNum - 1) * request.PerPage); return new Response( total, [..list.Select((c, i) => new Response.Row( Num: startNum - i, c.ID, c.FeedSourceName, c.Title, c.Author, c.Link, c.PublishedAt, c.CreatedAt ))] ); } } }