using Application.Abstractions.Data; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Channel.List { public class WriteModel(IMediator mediator, IAppDbContext db) : PageModel { public string QueryString { get; private set; } = ""; [BindProperty] public InputModel Input { get; set; } = new(); public sealed class InputModel { [DisplayName("회원 ID")] [Required(ErrorMessage = "{0}은 필수입니다.")] public int MemberID { get; set; } [DisplayName("SID")] [Required(ErrorMessage = "{0}은 필수입니다.")] [StringLength(24, MinimumLength = 24, ErrorMessage = "{0}은 {1}자여야 합니다.")] public string SID { get; set; } = default!; [DisplayName("이름")] [Required(ErrorMessage = "{0}은 필수입니다.")] [StringLength(200, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")] public string Name { get; set; } = default!; [DisplayName("핸들")] [StringLength(30, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")] public string? Handle { get; set; } [DisplayName("YouTube 주소")] [Required(ErrorMessage = "{0}은 필수입니다.")] [StringLength(255, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")] public string YouTubeUrl { get; set; } = default!; [DisplayName("수수료(%)")] [Range(0, 100, ErrorMessage = "{0}은 {1}~{2} 사이여야 합니다.")] public decimal PlatformFeeRate { get; set; } = 0; [DisplayName("인증 여부")] public bool IsVerified { get; set; } = false; [DisplayName("사용 여부")] public bool IsActive { get; set; } = false; } public Task OnGetAsync(CancellationToken _) { QueryString = HttpContext.Request.QueryString.HasValue ? HttpContext.Request.QueryString.Value!.TrimStart('?') : ""; return Task.CompletedTask; } public async Task OnGetSearchMemberAsync(string keyword, CancellationToken ct) { if (string.IsNullOrWhiteSpace(keyword) || keyword.Trim().Length < 1) { return new JsonResult(Array.Empty()); } var kw = keyword.Trim(); var isNumeric = int.TryParse(kw, out var numericId); var list = await db.Member .AsNoTracking() .Where(x => (isNumeric && x.ID == numericId) || x.SID.Contains(kw) || x.Email.Contains(kw) || (x.Name != null && x.Name.Contains(kw)) ) .OrderByDescending(x => x.ID) .Take(10) .Select(x => new { id = x.ID, email = x.Email, name = x.Name, sid = x.SID }) .ToListAsync(ct); return new JsonResult(list); } public async Task OnPostAsync(CancellationToken ct) { try { if (!ModelState.IsValid) { throw new Exception("유효성 검사에 실패했습니다."); } await mediator.Send(new CreateChannel.Command( Input.MemberID, Input.SID, Input.Name, Input.Handle, Input.YouTubeUrl, Input.PlatformFeeRate, Input.IsVerified, Input.IsActive ), ct); TempData["SuccessMessage"] = "채널이 등록되었습니다."; return RedirectToPage("/Channel/List/Index"); } catch (Exception e) { TempData["ErrorMessages"] = e.Message; return Page(); } } } }