using SharedKernel.Helpers; using SharedKernel.Extensions; using Application.Abstractions.YouTube; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Channel.List { public class IndexModel(IMediator mediator, IYouTubeLiveStateStore liveStateStore) : PageModel { [BindProperty(SupportsGet = true)] public QueryParams Query { get; set; } = new(); public sealed class QueryParams { public int? Search { get; set; } public string? Keyword { get; set; } public string? StartAt { get; set; } public string? EndAt { get; set; } public bool? IsVerified { get; set; } [Range(1, int.MaxValue)] [DisplayName("페이지 번호")] public int PageNum { get; set; } = 1; [Range(1, 100)] [DisplayName("페이지 목록 수")] public ushort PerPage { get; set; } = 20; } public int Total { get; set; } = 0; public List<( int Num, int ID, string SID, string Name, string? Handle, string YouTubeUrl, decimal PlatformFeeRate, char IsVerified, char IsActive, int MemberID, string? MemberName, string? MemberEmail, string? UpdatedAt, string CreatedAt )> List { get; set; } = []; public Pagination? Pagination { get; set; } /// 현재 라이브 중인 채널 SID(=YouTube 채널 ID) 집합 public HashSet LiveChannelIds { get; set; } = []; public async Task OnGetAsync(CancellationToken ct) { if (!ModelState.IsValid) { return; } var result = await mediator.Send(new SearchChannels.Query( Query.Search, Query.Keyword, Query.IsVerified, Query.StartAt, Query.EndAt, Query.PageNum, Query.PerPage ), ct); Total = result.Total; List = [..result.List.Select(c => ( c.Num, c.ID, c.SID, c.Name, c.Handle, c.YouTubeUrl, c.PlatformFeeRate, c.IsVerified ? 'Y' : 'N', c.IsActive ? 'Y' : 'N', c.MemberID, c.MemberName ?? "-", c.MemberEmail ?? "-", c.UpdatedAt.GetDateAt() ?? "-", c.CreatedAt.GetDateAt() ))]; Pagination = new Pagination(result.Total, Query.PageNum, Query.PerPage); // Redis에서 현재 라이브 중인 채널 ID 조회 (API 호출 없음) var allLive = await liveStateStore.GetAllLiveAsync(); LiveChannelIds = [..allLive.Select(l => l.ChannelId)]; } public async Task OnPostDeleteAsync(int[] ids, CancellationToken ct) { try { await mediator.Send(new DeleteChannel.Command(ids), ct); TempData["SuccessMessage"] = $"{ids.Length}건이 삭제되었습니다."; } catch (Exception e) { TempData["ErrorMessages"] = e.Message; } return RedirectToPage("/Channel/List/Index", Query); } } }