using SharedKernel.Extensions; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Crypto { public class CategoryModel(IMediator mediator) : PageModel { public int Total { get; private set; } = 0; public List<( int Num, int ID, int Index, string Code, string Name, short Order, char IsActive, int CoinCount, string? UpdatedAt, string CreatedAt )> List { get; set; } = []; [BindProperty(Name = "request")] public List Input { get; private set; } = []; public List Data { get; private set; } = []; public sealed class InputModel { public int? ID { get; set; } [Required] [StringLength(30)] public required string Code { get; set; } [Required] [StringLength(100)] public required string Name { get; set; } [Range(-9999, 9999)] public short Order { get; set; } public bool IsActive { get; set; } = false; } public async Task OnGetAsync(CancellationToken ct) { if (!ModelState.IsValid) { return; } var result = await mediator.Send(new GetCryptoCategories.Query(), ct); Total = result.Total; List = [..result.List.Select(c => ( c.Num, c.ID, c.Index, c.Code, c.Name, c.Order, c.IsActive ? 'Y' : 'N', (int)c.CoinCount, c.UpdatedAt.GetDateAt() ?? "-", c.CreatedAt.GetDateAt() ))]; Data = [..result.List.Select(x => new InputModel { ID = x.ID, Code = x.Code, Name = x.Name, Order = x.Order, IsActive = x.IsActive })]; } public async Task OnPostAsync(CancellationToken ct) { try { if (!ModelState.IsValid) { throw new Exception(); } var cmd = new SaveCryptoCategories.Command( [..Input.Select(x => new SaveCryptoCategories.Command.Row( x.ID, x.Code, x.Name, x.Order, x.IsActive ))] ); var response = await mediator.Send(cmd, ct); TempData["SuccessMessage"] = $"저장 완료 (추가: {response.Inserted}, 수정: {response.Updated}, 삭제: {response.Deleted})"; } catch (Exception e) { TempData["ErrorMessages"] = e.Message; } return RedirectToPage("/Crypto/Category"); } } }