카테고리 없음

ejs, js, nestjs 팔로우 리스트 연결

S0 2024. 4. 24. 10:46

 

팔로워, 팔로잉 리스트를 연결해오고,

리스트마다 버튼을 만들어서 팔로우 상태와 연동하여

팔로우가 안 된 유저면 팔로잉, 팔로우가 되어있는 유저면 언팔로우라는 텍스트가 버튼에 나오도록 코드를 작성했다.

예제는 팔로워 리스트인데, 팔로잉 리스트도 똑같은 js 파일을 적용하면 된다.

 

 

follower.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chillinker follower list</title>
    <link rel="stylesheet" href="/css/style.css" />
    <link rel="stylesheet" href="/css/following.css" />
    <link
      rel="icon"
      type="image/png"
      sizes="16×16"
      href="/logo_image/favicon-16x16.png"
    />
    <style>
        @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR:wght@100;200;300;400;500;600;700&family=Sriracha&display=swap');
      </style>
      <script
        src="https://kit.fontawesome.com/0b832ce4c1.js"
        crossorigin="anonymous"
      ></script>
      <link
      rel="icon"
      type="image/png"
      sizes="16×16"
      href="/logo_image/favicon-16x16.png"
    />
</head>
<body>
    <div class="wrap">
      <%- include('header.ejs') %>
        <main>
          <div class="inner">
            <div class="following_title">
                <span>팔로워</span>            
            </div>
            <ul class="following_list">
              <% followerList.forEach(function(follower,index) { %>
                <li>
                    <a class="profile_link" href="#">
                      <span class="followId" id="followId-<%= index %>" style="display:none;"><%= follower.followers_id.id %></span>
                    <% if (follower.followers_profile_image) { %>
                        <img src="<%= follower.followers_profile_image %>" alt="profile image">
                    <% } else { %>
                        <img src="/logo_image/chillinker_logo(2).png" alt="default profile image">
                    <% } %>
                        <span class="name"><%= follower.followers_nickname %></span>
                        <span class="intro"><%= follower.followers_intro %></span>
                    </a>
                    <button class="unfollowing_btn" id="<%= follower.followers_id %>-<%= index %>" data-is-following="<%= follower.isFollowing %>">
                      <% if (follower.isFollowing) { %>
                          언팔로우
                      <% } else { %>
                          팔로잉
                      <% } %>
                  </button>
                </li>
                <% }); %>
            </ul>
          </div>
        </main>
        <%- include('footer.ejs') %>
      </div>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="/js/follow.js"></script>
    </body>
</html>

 

 

follow.js

document.addEventListener('DOMContentLoaded', function () {
  const followBtns = document.querySelectorAll('.unfollowing_btn');

  followBtns.forEach(function (followBtn) {
    const isFollowing = followBtn.dataset.isFollowing === 'true';
    updateButtonState(followBtn, isFollowing);

    followBtn.addEventListener('click', function () {
      const followId = this.id.split('-')[0];
      const isFollowing = this.dataset.isFollowing === 'true';

      const newState = !isFollowing;
      updateButtonState(followBtn, newState);

      $.ajax({
        type: 'Post',
        url: `/users/${followId}/follows/follow`,
        contentType: 'application/json',
        data: JSON.stringify({ isFollowing: newState }),
        success: function (data) {
          localStorage.setItem(`followStatus-${followId}`, newState);
          location.reload(true);
        },
        error: function (response) {
          updateButtonState(followBtn, isFollowing);
          alert(response.responseJSON.message);
        },
      });
    });
  });

  function updateButtonState(button, isFollowing) {
    button.textContent = isFollowing ? '팔로잉' : '언팔로우';
    button.dataset.isFollowing = isFollowing;
  }

  followBtns.forEach(function (followBtn) {
    const followId = followBtn.id.split('-')[0];
    const storedStatus = localStorage.getItem(`followStatus-${followId}`);
    if (storedStatus !== null) {
      const isFollowing = storedStatus === 'true';
      updateButtonState(followBtn, isFollowing);
    }
  });
});

 

 

follow.controller.ts

@ApiOperation({ summary: '내 팔로워 목록 조회' })
  @UseGuards(AuthGuard('jwt'))
  @Get('/user/follower')
  @Render('follower')
  async getMyFollower(@UserInfo() user: Users) {
    const followerList = await this.followService.getFollowerList(user.id);

    for (const follower of followerList) {
      follower.isFollowing = await this.followService.isFollowing(
        follower.id,
        user.id,
      );
    }

    return { followerList };
  }
  
  
  @ApiOperation({ summary: '팔로우/언팔로우' })
  @HttpCode(201)
  @UseGuards(AuthGuard('jwt'))
  @Post('users/:id/follows/follow')
  async follow(@Param('id') followingId: number, @UserInfo() user: Users) {
    const followerId = user.id;

    if (followingId === followerId) {
      throw new BadRequestException('스스로를 팔로우 할 수는 없습니다');
    }
    await this.followService.follow(followingId, followerId);
  }

 

 

follow.service.ts

async isFollowing(followingId: number, followerId: number): Promise<boolean> {
    const followRelation = { followingId, followerId };
    const existingFollow = await this.followRepository.findOne({
      where: followRelation,
    });
    return !!existingFollow; // 반환값으로 팔로우 여부를 불리언 값으로 반환
  }

 


유저 네임은 팀원들 이름을 빌려와서 가렸다

결과물!

이렇게 팔로잉 상태에 따라 버튼의 텍스트가 변경되고,

js에 리로드 코드를 넣어줬기 때문에 상태 변경 후 새로고침까지 자동으로 완료되어 실시간 갱신이 가능하다.