using SharedKernel.Attributes; using SharedKernel.Extensions; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Crypto.List { public class WriteModel(IMediator mediator) : PageModel { public string? QueryString { get; set; } public List Categories { get; set; } = []; [BindProperty] public InputModel Input { get; set; } = new(); public sealed class InputModel { [Required(ErrorMessage = "심볼은 필수입니다.")] [StringLength(30, ErrorMessage = "심볼은 {1}자 이하로 입력하세요.")] public string Symbol { get; set; } = null!; [Required(ErrorMessage = "한글명은 필수입니다.")] [StringLength(200, ErrorMessage = "한글명은 {1}자 이하로 입력하세요.")] public string KorName { get; set; } = null!; [Required(ErrorMessage = "영문명은 필수입니다.")] [StringLength(200, ErrorMessage = "영문명은 {1}자 이하로 입력하세요.")] public string EngName { get; set; } = null!; [AllowedExtensions("jpg,jpeg,png,gif,webp,svg", ErrorMessage = "이미지 확장자는 jpg, jpeg, png, gif, webp, svg 이어야 합니다.")] public IFormFile? LogoImageFile { get; set; } [StringLength(5000)] public string? Description { get; set; } [StringLength(100)] public string? ContractAddress { get; set; } [StringLength(500)] [DataType(DataType.Url)] public string? WebsiteUrl { get; set; } [StringLength(500)] [DataType(DataType.Url)] public string? WhitepaperUrl { get; set; } [StringLength(500)] [DataType(DataType.Url)] public string? TwitterUrl { get; set; } [StringLength(500)] [DataType(DataType.Url)] public string? TelegramUrl { get; set; } public bool IsActive { get; set; } = false; public bool IsWarning { get; set; } = false; public bool IsNew { get; set; } = false; public bool IsDelisted { get; set; } = false; public int[] CategoryIDs { get; set; } = []; } public async Task OnGetAsync(CancellationToken ct) { var categories = await mediator.Send(new GetCryptoCategories.Query(), ct); Categories = [..categories.List.Select(c => new SelectListItem(c.Name, c.ID.ToString()))]; QueryString = Request.QueryString.ToString(); } public async Task OnPostAsync(CancellationToken ct) { try { if (!ModelState.IsValid) { throw new Exception(ModelState.GetErrorMessages()); } await mediator.Send(new CreateCoin.Command( Input.Symbol, Input.KorName, Input.EngName, Input.LogoImageFile, Input.Description, Input.ContractAddress, Input.WebsiteUrl, Input.WhitepaperUrl, Input.TwitterUrl, Input.TelegramUrl, Input.IsActive, Input.IsWarning, Input.IsNew, Input.IsDelisted, Input.CategoryIDs ), ct); TempData["SuccessMessage"] = $"{Input.Symbol} 코인이 등록되었습니다."; return RedirectToPage("/Crypto/List/Index"); } catch (Exception e) { TempData["ErrorMessages"] = e.Message; return Redirect($"/Crypto/List/Write?{Request.QueryString}"); } } } }