using SharedKernel.Extensions; using SharedKernel.Helpers; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Crypto.News { public class ArticlesModel(IMediator mediator) : PageModel { [BindProperty(SupportsGet = true)] public QueryParams Query { get; set; } = new(); public List Sources { get; set; } = []; public sealed class QueryParams { [Range(1, int.MaxValue)] [DisplayName("페이지 번호")] public int PageNum { get; set; } = 1; [Range(1, 100)] [DisplayName("페이지 당 수")] public ushort PerPage { get; set; } = 20; [DisplayName("소스")] public int? RssFeedSourceID { get; set; } [DisplayName("검색어")] public string? Keyword { get; set; } } public int Total { get; set; } public List<( int Num, int ID, string FeedSourceName, string Title, string? Author, string? Link, string? PublishedAt, string CreatedAt )> List { get; set; } = []; public Pagination? Pagination { get; set; } public async Task OnGetAsync(CancellationToken ct) { if (!ModelState.IsValid) { return; } var sources = await mediator.Send(new GetAllNewsSources.Query(), ct); Sources = [..sources.Sources.Select(s => new SelectListItem(s.Name, s.ID.ToString()))]; var result = await mediator.Send(new SearchNewsArticles.Query( Query.RssFeedSourceID, Query.Keyword, Query.PageNum, Query.PerPage ), ct); Total = result.Total; List = [..result.List.Select(c => ( c.Num, c.ID, c.FeedSourceName, c.Title, c.Author, c.Link, c.PublishedAt.GetDateAt() ?? "-", c.CreatedAt.GetDateAt() ))]; Pagination = new Pagination(result.Total, Query.PageNum, Query.PerPage); } public async Task OnPostDeleteAsync(int[] ids, CancellationToken ct) { try { await mediator.Send(new DeleteNewsArticles.Command(ids), ct); TempData["SuccessMessage"] = $"{ids.Length}개 기사가 삭제되었습니다."; } catch (Exception e) { TempData["ErrorMessages"] = e.Message; } return RedirectToPage("/Crypto/News/Articles", Query); } } }