팔로워, 팔로잉 리스트를 연결해오고,
리스트마다 버튼을 만들어서 팔로우 상태와 연동하여
팔로우가 안 된 유저면 팔로잉, 팔로우가 되어있는 유저면 언팔로우라는 텍스트가 버튼에 나오도록 코드를 작성했다.
예제는 팔로워 리스트인데, 팔로잉 리스트도 똑같은 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에 리로드 코드를 넣어줬기 때문에 상태 변경 후 새로고침까지 자동으로 완료되어 실시간 갱신이 가능하다.