Answer.cshtml.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using SharedKernel.Extensions;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.AspNetCore.Identity;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.AspNetCore.Mvc.RazorPages;
  6. using Infrastructure.Persistence.Identity;
  7. using System.ComponentModel;
  8. using System.ComponentModel.DataAnnotations;
  9. namespace Admin.Pages.Forum.Posts.List;
  10. public class AnswerModel(IMediator mediator, UserManager<ApplicationUser> userManager) : PageModel
  11. {
  12. public int ID { get; set; }
  13. public int BoardID { get; set; }
  14. public string BoardName { get; set; } = default!;
  15. public string? BoardPrefixName { get; set; }
  16. public string? BoardPrefixColor { get; set; }
  17. public string Subject { get; set; } = default!;
  18. public new string Content { get; set; } = default!;
  19. public string? Name { get; set; }
  20. public string? SID { get; set; }
  21. public bool IsSecret { get; set; }
  22. public bool IsAnswered => Answers.Count > 0;
  23. public string CreatedAt { get; set; } = default!;
  24. public List<FileItemView> Files { get; set; } = [];
  25. public List<AnswerItemView> Answers { get; set; } = [];
  26. public string? ReturnUrl { get; set; }
  27. public string? QueryString { get; set; }
  28. public sealed record FileItemView(int ID, string FileName, string Url, long? Size);
  29. public sealed record AnswerItemView(int ID, string? Name, string Content, string CreatedAt);
  30. [BindProperty]
  31. public InputModel Input { get; set; } = new();
  32. public sealed class InputModel
  33. {
  34. [DisplayName("답변 내용")]
  35. [Required(ErrorMessage = "{0}을 입력해주세요.")]
  36. public string Content { get; set; } = null!;
  37. [DisplayName("첨부파일")]
  38. public List<IFormFile>? Files { get; set; }
  39. }
  40. public async Task<IActionResult> OnGetAsync(int id, CancellationToken ct)
  41. {
  42. var loaded = await LoadAsync(id, ct);
  43. if (!loaded)
  44. {
  45. return RedirectToPage("/Forum/Posts/List/Index");
  46. }
  47. return Page();
  48. }
  49. public async Task<IActionResult> OnPostAsync(int id, CancellationToken ct)
  50. {
  51. if (!ModelState.IsValid)
  52. {
  53. TempData["ErrorMessages"] = ModelState.GetErrorMessages();
  54. return RedirectToPage("/Forum/Posts/List/Answer", new { id });
  55. }
  56. var admin = await userManager.GetUserAsync(User);
  57. var result = await mediator.Send(new CreateAnswerComment.Command(
  58. id,
  59. Input.Content,
  60. Input.Files,
  61. admin?.Email
  62. ), ct);
  63. if (result.IsFailure)
  64. {
  65. TempData["ErrorMessages"] = result.Error.Description;
  66. }
  67. else
  68. {
  69. TempData["SuccessMessage"] = "답변이 등록되었습니다.";
  70. }
  71. return RedirectToPage("/Forum/Posts/List/Answer", new { id });
  72. }
  73. private async Task<bool> LoadAsync(int id, CancellationToken ct)
  74. {
  75. var postResult = await mediator.Send(new GetPost.Query(id), ct);
  76. if (postResult.IsFailure)
  77. {
  78. TempData["ErrorMessages"] = postResult.Error.Description;
  79. return false;
  80. }
  81. var post = postResult.Value;
  82. if (!post.IsQnA)
  83. {
  84. TempData["ErrorMessages"] = "1:1 문의 게시판의 게시글이 아닙니다.";
  85. return false;
  86. }
  87. ID = post.ID;
  88. BoardID = post.BoardID;
  89. BoardName = post.BoardName;
  90. BoardPrefixName = post.BoardPrefixName;
  91. BoardPrefixColor = post.BoardPrefixColor;
  92. Subject = post.Subject;
  93. Content = post.Content;
  94. Name = post.Name;
  95. SID = post.SID;
  96. IsSecret = post.IsSecret;
  97. CreatedAt = post.CreatedAt.GetDateAt();
  98. Files = [..post.Files.Where(c => !c.IsDisabled).Select(c => new FileItemView(c.ID, c.FileName, c.Url, c.Size))];
  99. // 기존 답변 (게시글의 댓글, 오래된 순)
  100. var comments = await mediator.Send(new SearchComments.Query(null, id, null, null, null, null, null, 1, 100), ct);
  101. Answers = [..comments.List
  102. .Where(c => !c.IsDeleted)
  103. .OrderBy(c => c.ID)
  104. .Select(c => new AnswerItemView(c.ID, c.Name ?? c.SID, c.Content, c.CreatedAt.GetDateAt()))];
  105. ReturnUrl = Request.Headers.Referer.ToString();
  106. QueryString = Request.QueryString.ToString();
  107. return true;
  108. }
  109. }