Edit.cshtml.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using Domain.Entities.Members.ValueObject;
  2. using SharedKernel.Attributes;
  3. using SharedKernel.Extensions;
  4. using SharedKernel.Storage;
  5. using MediatR;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.AspNetCore.Mvc.RazorPages;
  8. using Microsoft.AspNetCore.Mvc.Rendering;
  9. using System.ComponentModel;
  10. using System.ComponentModel.DataAnnotations;
  11. namespace Admin.Pages.Member.List;
  12. public class EditModel(IMediator mediator, IFileStorage fileStorage) : PageModel
  13. {
  14. private static readonly string[] AllowedFileExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp"];
  15. [BindProperty]
  16. public string? QueryString { get; set; }
  17. public List<SelectListItem> MemberGradeList { get; set; } = [];
  18. public string? Thumb { get; set; }
  19. public string? Icon { get; set; }
  20. public string? EmailVerifiedAt { get; set; }
  21. public string? AuthCertifiedAt { get; set; }
  22. public string? DeniedAt { get; set; }
  23. public string? DeletedAt { get; set; }
  24. public string? UpdatedAt { get; set; }
  25. public string? CreatedAt { get; set; }
  26. [BindProperty]
  27. public InputModel Input { get; set; } = new();
  28. public sealed class InputModel
  29. {
  30. [Required]
  31. public int ID { get; set; }
  32. [DisplayName("회원등급")]
  33. public int? MemberGradeID { get; set; }
  34. [DisplayName("이메일")]
  35. [Required(ErrorMessage = "{0}은(는) 필수입니다.")]
  36. [EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")]
  37. [StringLength(60, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  38. public string Email { get; set; } = default!;
  39. [DisplayName("별명")]
  40. [Required(ErrorMessage = "{0}은(는) 필수입니다.")]
  41. [StringLength(20, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  42. public string? Name { get; set; }
  43. [DisplayName("비밀번호")]
  44. [MinLength(4, ErrorMessage = "{0}은(는) {1}자 이상 입력하세요.")]
  45. public string? Password { get; set; }
  46. [DisplayName("성")]
  47. [StringLength(20, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  48. public string? FirstName { get; set; }
  49. [DisplayName("이름")]
  50. [StringLength(40, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  51. public string? LastName { get; set; }
  52. [DisplayName("자기소개")]
  53. [StringLength(1000, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  54. public string? Intro { get; set; }
  55. [DisplayName("한마디")]
  56. [StringLength(50, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
  57. public string? Summary { get; set; }
  58. [DisplayName("연락처")]
  59. [StringLength(15)]
  60. public string? Phone { get; set; }
  61. [DisplayName("성별")]
  62. public Gender? Gender { get; set; }
  63. [DisplayName("생년월일")]
  64. public DateOnly? Birthday { get; set; }
  65. [DisplayName("사진")]
  66. [AllowedExtensions("jpg,jpeg,png,gif,webp", ErrorMessage = "이미지 형식은 jpg, jpeg, png, gif, webp 파일이어야 합니다.")]
  67. public IFormFile? Thumb { get; set; }
  68. [DisplayName("아이콘")]
  69. [AllowedExtensions("jpg,jpeg,png,gif,webp", ErrorMessage = "이미지 형식은 jpg, jpeg, png, gif, webp 파일이어야 합니다.")]
  70. public IFormFile? Icon { get; set; }
  71. [DisplayName("이메일 인증")]
  72. public bool IsEmailVerified { get; set; }
  73. [DisplayName("본인 인증")]
  74. public bool IsAuthCertified { get; set; }
  75. [DisplayName("차단 여부")]
  76. public bool IsDenied { get; set; }
  77. [DisplayName("관리자 여부")]
  78. public bool IsAdmin { get; set; }
  79. [DisplayName("탈퇴 여부")]
  80. public bool IsWithdraw { get; set; }
  81. }
  82. public async Task OnGetAsync(int id, CancellationToken ct)
  83. {
  84. await LoadMemberGradeList(ct);
  85. var result = await mediator.Send(new GetMember.Query(id), ct);
  86. if (result is null)
  87. {
  88. return;
  89. }
  90. Thumb = result.Thumb;
  91. Icon = result.Icon;
  92. EmailVerifiedAt = result.EmailVerifiedAt.GetDateAt();
  93. AuthCertifiedAt = result.AuthCertifiedAt.GetDateAt();
  94. DeniedAt = result.DeniedAt.GetDateAt();
  95. DeletedAt = result.DeletedAt.GetDateAt();
  96. UpdatedAt = result.UpdatedAt.GetDateAt();
  97. CreatedAt = result.CreatedAt.GetDateAt();
  98. Input = new InputModel
  99. {
  100. ID = result.ID,
  101. MemberGradeID = result.MemberGradeID,
  102. Email = result.Email,
  103. Name = result.Name,
  104. FirstName = result.FirstName,
  105. LastName = result.LastName,
  106. Intro = result.Intro,
  107. Summary = result.Summary,
  108. Phone = result.Phone,
  109. Gender = result.Gender,
  110. Birthday = result.Birthday,
  111. IsEmailVerified = result.IsEmailVerified,
  112. IsAuthCertified = result.IsAuthCertified,
  113. IsDenied = result.IsDenied,
  114. IsAdmin = result.IsAdmin,
  115. IsWithdraw = result.IsWithdraw
  116. };
  117. QueryString = Request.QueryString.ToString();
  118. }
  119. public async Task<IActionResult> OnPostAsync(bool isThumbRemove, bool isIconRemove, CancellationToken ct)
  120. {
  121. try
  122. {
  123. if (!ModelState.IsValid)
  124. {
  125. throw new Exception(ModelState.GetErrorMessages());
  126. }
  127. // 파일 저장 (PageModel에서 처리)
  128. string? thumbUrl = null;
  129. string? iconUrl = null;
  130. if (Input.Thumb is not null)
  131. {
  132. var thumbPath = new FileStoragePath(UploadTarget.Upload, UploadFolder.MemberThumb, Input.ID);
  133. thumbUrl = (await fileStorage.SaveFileAsync(Input.Thumb, thumbPath, AllowedFileExtensions, ct))?.Url;
  134. }
  135. if (Input.Icon is not null)
  136. {
  137. var iconPath = new FileStoragePath(UploadTarget.Upload, UploadFolder.MemberIcon, Input.ID);
  138. iconUrl = (await fileStorage.SaveFileAsync(Input.Icon, iconPath, AllowedFileExtensions, ct))?.Url;
  139. }
  140. await mediator.Send(new UpdateMember.Command(
  141. Input.ID,
  142. Input.MemberGradeID,
  143. Input.Email,
  144. Input.Name,
  145. Input.Password,
  146. Input.FirstName,
  147. Input.LastName,
  148. Input.Intro,
  149. Input.Summary,
  150. Input.Phone,
  151. Input.Birthday,
  152. Input.Gender,
  153. thumbUrl,
  154. isThumbRemove,
  155. iconUrl,
  156. isIconRemove,
  157. Input.IsEmailVerified,
  158. Input.IsAuthCertified,
  159. Input.IsDenied,
  160. Input.IsAdmin,
  161. Input.IsWithdraw
  162. ), ct);
  163. TempData["SuccessMessage"] = "회원 정보가 수정되었습니다.";
  164. }
  165. catch (Exception e)
  166. {
  167. TempData["ErrorMessages"] = e.Message;
  168. }
  169. return Redirect($"/Member/List/Edit/{Input.ID}{QueryString}");
  170. }
  171. private async Task LoadMemberGradeList(CancellationToken ct)
  172. {
  173. var grades = await mediator.Send(new GetMemberGrades.Query(), ct);
  174. MemberGradeList = [.. grades.List.Select(g => new SelectListItem
  175. {
  176. Value = g.ID.ToString(),
  177. Text = g.KorName
  178. })];
  179. }
  180. }