Handler.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. using SharedKernel.Results;
  5. namespace Application.Features.Api.Member.Profile;
  6. public sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  7. {
  8. private const string FeedBoardCode = "feed";
  9. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  10. {
  11. var member = await db.Member.AsNoTracking()
  12. .Where(m => m.SID == request.MemberSID && !m.IsWithdraw && !m.IsDenied)
  13. .Select(m => new
  14. {
  15. m.ID,
  16. m.SID,
  17. m.Name,
  18. m.Thumb,
  19. m.BannerUrl,
  20. m.Summary,
  21. m.Intro,
  22. m.IsCreator,
  23. m.IsAdmin,
  24. m.IsAuthCertified,
  25. JoinedAt = m.CreatedAt,
  26. m.LastLoginAt,
  27. ChannelSID = m.Channel != null ? m.Channel.SID : null,
  28. ChannelHandle = m.Channel != null ? m.Channel.Handle : null,
  29. Stats = m.MemberStats == null ? null : new
  30. {
  31. m.MemberStats.FollowerCount,
  32. m.MemberStats.FollowingCount,
  33. m.MemberStats.PostCount,
  34. m.MemberStats.CommentCount,
  35. m.MemberStats.AttendanceCount,
  36. m.MemberStats.Exp,
  37. m.MemberStats.LikeReceivedCount
  38. }
  39. })
  40. .FirstOrDefaultAsync(ct);
  41. if (member is null)
  42. {
  43. return Result.Failure<Response>(Error.NotFound("Member.ProfileNotFound", "회원을 찾을 수 없습니다."));
  44. }
  45. var feedBoardID = await db.Board.AsNoTracking().Where(b => b.Code == FeedBoardCode).Select(b => (int?)b.ID).FirstOrDefaultAsync(ct);
  46. var feedPostCount = feedBoardID is int fid
  47. ? await db.Post.AsNoTracking().LongCountAsync(p => p.BoardID == fid && p.MemberID == member.ID && !p.IsDeleted, ct)
  48. : 0;
  49. var consecutiveDays = await db.Attendance.AsNoTracking()
  50. .Where(a => a.MemberID == member.ID)
  51. .OrderByDescending(a => a.CreatedAt)
  52. .Select(a => (int?)a.ConsecutiveDays)
  53. .FirstOrDefaultAsync(ct) ?? 0;
  54. var viewerID = request.ViewerMemberID ?? 0;
  55. var isSelf = viewerID > 0 && viewerID == member.ID;
  56. var isFollowing = false;
  57. if (viewerID > 0 && !isSelf)
  58. {
  59. isFollowing = await db.MemberFollow.AsNoTracking().AnyAsync(f => f.FollowerMemberID == viewerID && f.FolloweeMemberID == member.ID, ct);
  60. }
  61. return new Response
  62. {
  63. MemberID = member.ID,
  64. MemberSID = member.SID,
  65. Name = member.Name,
  66. Thumb = member.Thumb,
  67. BannerUrl = member.BannerUrl,
  68. Summary = member.Summary,
  69. Intro = member.Intro,
  70. IsCreator = member.IsCreator,
  71. IsAdmin = member.IsAdmin,
  72. IsAuthCertified = member.IsAuthCertified,
  73. JoinedAt = member.JoinedAt,
  74. LastLoginAt = member.LastLoginAt,
  75. ChannelSID = member.ChannelSID,
  76. ChannelHandle = member.ChannelHandle,
  77. FollowerCount = member.Stats?.FollowerCount ?? 0,
  78. FollowingCount = member.Stats?.FollowingCount ?? 0,
  79. PostCount = member.Stats?.PostCount ?? 0,
  80. CommentCount = member.Stats?.CommentCount ?? 0,
  81. FeedPostCount = feedPostCount,
  82. AttendanceCount = member.Stats?.AttendanceCount ?? 0,
  83. ConsecutiveDays = consecutiveDays,
  84. Exp = member.Stats?.Exp ?? 0,
  85. LikeReceivedCount = member.Stats?.LikeReceivedCount ?? 0,
  86. IsFollowing = isFollowing,
  87. IsSelf = isSelf
  88. };
  89. }
  90. }