Handler.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using Domain.Entities.Forum.ValueObject;
  4. using SharedKernel.Results;
  5. using Microsoft.EntityFrameworkCore;
  6. namespace Application.Features.Api.Forum.Post.Get;
  7. public sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  8. {
  9. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  10. {
  11. // 게시글 조회
  12. var item = await db.Post.AsNoTracking()
  13. .Include(c => c.Board)
  14. .Include(c => c.BoardPrefix)
  15. .Include(c => c.Member).ThenInclude(m => m.MemberGrade)
  16. .Include(c => c.PostTag).ThenInclude(t => t.Tag)
  17. .FirstOrDefaultAsync(x => x.ID == request.ID, ct);
  18. if (item is null)
  19. {
  20. return Result.Failure<Response>(
  21. Error.NotFound("Post.NotFound", "게시글을 찾을 수 없습니다.")
  22. );
  23. }
  24. // 이전/다음 게시글
  25. var prevID = await db.Post.AsNoTracking()
  26. .Where(x => x.BoardID == item.BoardID && x.ID < item.ID && !x.IsDeleted)
  27. .OrderByDescending(x => x.ID)
  28. .Select(x => (int?)x.ID)
  29. .FirstOrDefaultAsync(ct);
  30. var nextID = await db.Post.AsNoTracking()
  31. .Where(x => x.BoardID == item.BoardID && x.ID > item.ID && !x.IsDeleted)
  32. .OrderBy(x => x.ID)
  33. .Select(x => (int?)x.ID)
  34. .FirstOrDefaultAsync(ct);
  35. // 사용자별 상태
  36. bool hasLike = false, hasDislike = false, hasBookmark = false, hasReport = false;
  37. if (request.MemberID is int memberID)
  38. {
  39. hasLike = await db.PostReaction.AsNoTracking().AnyAsync(x => x.PostID == item.ID && x.MemberID == memberID && x.Reaction == Reaction.Like, ct);
  40. hasDislike = await db.PostReaction.AsNoTracking().AnyAsync(x => x.PostID == item.ID && x.MemberID == memberID && x.Reaction == Reaction.Dislike, ct);
  41. hasBookmark = await db.PostBookmark.AsNoTracking().AnyAsync(x => x.PostID == item.ID && x.MemberID == memberID, ct);
  42. hasReport = await db.PostReport.AsNoTracking().AnyAsync(x => x.PostID == item.ID && x.MemberID == memberID, ct);
  43. }
  44. // 태그 목록
  45. var tagList = item.PostTag.Select(t => new Response.TagDto(t.Tag.ID, t.Tag.Slug)).ToList();
  46. // 말머리
  47. Response.BoardPrefixDto? boardPrefix = item.BoardPrefix is not null
  48. ? new Response.BoardPrefixDto(
  49. item.BoardPrefix.ID,
  50. item.BoardPrefix.BoardID,
  51. item.BoardPrefix.Name,
  52. item.BoardPrefix.Color,
  53. item.BoardPrefix.Posts
  54. ) : null;
  55. // 작성자
  56. Response.WriterDto? writer = item.Member is not null
  57. ? new Response.WriterDto(
  58. item.Member.ID,
  59. item.Member.SID,
  60. item.Member.Name,
  61. item.Member.Thumb,
  62. item.Member.Icon,
  63. item.Member.MemberGrade?.Image,
  64. item.Member.Summary,
  65. item.Member.CreatedAt
  66. ) : null;
  67. return new Response(
  68. item.ID,
  69. item.BoardID,
  70. item.Board.Code,
  71. item.BoardPrefixID,
  72. item.MemberID,
  73. item.Subject,
  74. item.Content,
  75. item.SID,
  76. item.Email,
  77. item.Name,
  78. boardPrefix,
  79. writer,
  80. item.IsReply,
  81. item.IsAnonymous,
  82. item.IsSecret,
  83. item.IsNotice,
  84. item.IsSpeaker,
  85. item.Views,
  86. item.Likes,
  87. item.Dislikes,
  88. item.Comments,
  89. item.Reports,
  90. item.Images,
  91. item.Medias,
  92. item.Files,
  93. item.Tags,
  94. item.IpAddress,
  95. item.CreatedAt,
  96. tagList,
  97. prevID,
  98. nextID,
  99. hasLike,
  100. hasDislike,
  101. hasBookmark,
  102. hasReport
  103. );
  104. }
  105. }