using SharedKernel.Extensions; using SharedKernel.Helpers; using Application.Abstractions.Messaging; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Store.Coupon; public class IndexModel(IMediator mediator) : PageModel { [BindProperty(SupportsGet = true)] public QueryParams Query { get; set; } = new(); public List<(int ID, string Name)> Games { get; set; } = []; public sealed class QueryParams { [Range(1, int.MaxValue)] public int PageNum { get; set; } = 1; [Range(1, 100)] public ushort PerPage { get; set; } = 20; [DisplayName("게임")] public int? GameID { get; set; } [DisplayName("검색어")] public string? Keyword { get; set; } } public int Total { get; set; } public List<( int Num, int ID, string ProductName, string GameName, string Name, string UsagePolicyText, string? ExpiresAt, int GeneratedCount, int UsedCount, int AvailableCount, int LowStockThreshold, bool IsLowStock, string CreatedAt, string EditURL, string CodesURL )> List { get; set; } = []; public Pagination? Pagination { get; set; } public async Task OnGetAsync(CancellationToken ct) { if (!ModelState.IsValid) { return; } var gamesResult = await mediator.Send(new GetGames.Query(false), ct); Games = [.. gamesResult.List.Select(g => (ID: g.ID, Name: g.KorName))]; var result = await mediator.Send(new SearchCoupons.Query(Query.GameID, null, Query.Keyword, Query.PageNum, Query.PerPage), ct); Total = result.Total; List = [.. result.List.Select(c => ( c.Num, c.ID, c.ProductName, c.GameName, c.Name, UsagePolicyText: c.UsagePolicy == Domain.Entities.Store.ValueObject.CouponUsagePolicy.SingleUse ? "1회 사용" : "재사용", c.ExpiresAt?.ToString("yyyy-MM-dd"), c.GeneratedCount, c.UsedCount, c.AvailableCount, c.LowStockThreshold, c.IsLowStock, c.CreatedAt.GetDateAt(), EditURL: $"/Store/Coupon/Edit/{c.ID}{Request.QueryString}", CodesURL: $"/Store/Coupon/Codes/{c.ID}{Request.QueryString}" ))]; Pagination = new Pagination(result.Total, Query.PageNum, Query.PerPage); } public async Task OnPostDeleteAsync(int[] ids, CancellationToken ct) { if (ids is null || ids.Length == 0) { TempData["ErrorMessages"] = "삭제할 쿠폰을 선택해 주세요."; return RedirectToPage("/Store/Coupon/Index", Query); } var result = await mediator.Send(new DeleteCoupon.Command(ids), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; } else { TempData["SuccessMessage"] = $"{ids.Length}개 쿠폰이 삭제되었습니다."; } return RedirectToPage("/Store/Coupon/Index", Query); } }