classList.toggle()
querySelectorAll()
nodeList. for
๋ฌธ ๋๋ foreach
๋ฌธ์ ์ฌ์ฉ.MyConst
public final String PROFILE = "profile";
public final String PROFILE_LIST = "profileList";
public final String RESULT = "result";
public final String YOU_FOLLOW_ME = "youFollowMe";
commonHeader.html
<header th:fragment="header">
<span id="globalConst" sec:authorize="isAuthenticated()"
th:with="auth=${#authentication.getPrincipal().getUser()}"
th:attr="data-iuser=${auth.iuser}, data-writer=${auth.nm}, data-writer-profile=${auth.mainProfile}"></span>
...
<ul class="menus" sec:authorize="isAuthenticated()" th:with="auth=${#authentication.getPrincipal().getUser()}">
<li>
<a th:href="@{/user/profile}">
<span class="span__profile">
<img class="profile wh50" th:if="${auth.mainProfile != null}"
th:src="@{/pic/profile/{iuser}/{img}(iuser=${auth.iuser}, img=${auth.mainProfile})}">
<span th:text="${auth.nm}"></span>
</span>
</a>
</li>
...
</ul>
- ๋ก๊ทธ์ธํ ์ ์ ์ธ ๊ฒฝ์ฐ
auth
์ ์ ๋ณด๊ฐ ๋ด๊ธด๋ค- ์ฌ์ง ๋๋ ์ด๋ฆ์ ๋๋ฅด๋ฉด
/user/profile
๋ด ํ๋กํ๋ก ์ด๋ํ๋ค
feed.js
function moveToProfile(iuser) {
location.href = `/user/profile?iuser=${iuser}`;
}
- ํผ๋์์ ํ๋กํ์ฌ์ง์ ๋๋ฅด๋ฉด
/user/profile?iuser=${iuser}
๊ทธ ์ฌ๋์ ํ๋กํ๋ก ์ด๋ํ๋ค.
UserController
@GetMapping("/profile")
public void profile(Model model, UserEntity param, @AuthenticationPrincipal CustomUserPrincipal userDetails) {
System.out.println(param);
UserDTO param2 = new UserDTO();
param2.setYouIuser(param.getIuser());
if(param2.getYouIuser() == 0) {
param2.setYouIuser(userDetails.getUser().getIuser());
param.setIuser(userDetails.getUser().getIuser());
}
model.addAttribute(myConst.PROFILE, service.selUserProfile(param2));
model.addAttribute(myConst.PROFILE_LIST, service.selUserProfileList(param));
}
- ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ
UserEntity
์iuser
๊ฐ์ด ์๋ค๋ฉด
- ์ฆ, ๋์ ํ๋กํ๋ก ์ด๋ํ๋ ๊ฑฐ๋ผ๋ฉด
youIuser
(UserDTO
)์iuser
(UserEntity
)๋ ๋์ด๋ค.html
๋กprofile : UserDomain ๊ฐ์ฒด
,profileList : List<UserProfileEntity> ๊ฐ์ฒด
๋ฅผ ๋๊ฒจ์ค๋ค.
UserSerivce
@Autowired private IAuthenticationFacade auth;
public UserDomain selUserProfile(UserDTO param) {
param.setMeIuser(auth.getLoginUserPk());
return profileMapper.selUserProfile(param);
}
UserDTO
๋ฅผ ์ธํ ํด์ฃผ๊ณmapper
์ ๊ฒฐ๊ณผUserDomain์ ๊ฐ์ฒด
๋ฅผ ๋ฆฌํดํ๋ค.
- ๋์ ํ๋กํ๋ก ์ด๋ํ ๊ฒฝ์ฐ
YouIuser = ๋ , MeIuser = ๋
- ๋ค๋ฅธ ์ฌ๋์ ํ๋กํ๋ก ์ด๋ํ ๊ฒฝ์ฐ
YouIuser = ๊ทธ์ฌ๋ , MeIuser = ๋
UserProfileMapper
UserDomain selUserProfile(UserDTO param);
<select id="selUserProfile" resultType="UserDomain">
SELECT
A.iuser, A.email, A.nm, A.tel, A.mainProfile, A.regdt
, (SELECT COUNT(ifeed) FROM t_feed WHERE iuser = ${youIuser}) AS cntFeed
, (SELECT COUNT(iuserMe) FROM t_user_follow WHERE iuserMe = ${youIuser}) AS cntFollow
, (SELECT COUNT(iuserYou) FROM t_user_follow WHERE iuserYou = ${youIuser}) AS cntFollower
, (SELECT COUNT(iuserMe) FROM t_user_follow WHERE iuserMe = ${youIuser} AND iuserYou = ${meIuser}) AS isYouFollowMe
, (SELECT COUNT(iuserMe) FROM t_user_follow WHERE iuserMe = ${meIuser} AND iuserYou = ${youIuser}) AS isMeFollowYou
FROM t_user A
WHERE A.iuser = ${youIuser}
</select>
cntFeed
iuser
=๋ด ํ๋กํ : ๋
,๋ค๋ฅธ์ฌ๋ ํ๋กํ : ๊ทธ์ฌ๋
=${youIuser}
- ๋ด ํ๋กํ์ ๋ค์ด๊ฐ ๋๋ [ ๋ ]์.
- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋ [ ๊ทธ์ฌ๋์ ]
ifeed
๊ฐฏ์๋ฅผ.
cntFollow
iuserMe
=๋ด ํ๋กํ : ๋
,๋ค๋ฅธ์ฌ๋ ํ๋กํ : ๊ทธ์ฌ๋
=${youIuser}
- ๋ด๊ฐ ๋ค๋ฅธ์ฌ๋์ ํ๋ก์ฐํ(
iuserMe
) ๊ฐฏ์๋ฅผ (iuserMe
๊ฐ [ ๋ ]์ ์ ์ฅ์์ [ ๋ค๋ฅธ์ฌ๋ ]์ ํ๋ก์ฐํ ๊ฒ์ด๋ค.)- ๋ด ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๋ด
๊ฐ [ ๋ ] , (iuserMe = ${youIuser}
)- ๋ค๋ฅธ ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๊ทธ์ฌ๋
์ด [ ๋ ]
cntFollower
iuserYou
=๋ด ํ๋กํ : ๋
,๋ค๋ฅธ์ฌ๋ ํ๋กํ : ๊ทธ์ฌ๋
=${youIuser}
- ๋ค๋ฅธ์ฌ๋์ด ๋๋ฅผ ํ๋ก์ฐํ(iuserYou) ๊ฐฏ์๋ฅผ (
iuserYou
๊ฐ [ ๋ ]์ ์ ์ฅ์์ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋๋ฅผ ํ๋ก์ฐ ํ ๊ฒ์ด๋ค.)- ๋ด ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๋ด
๊ฐ [ ๋ ] (iuserYou = ${youIuser}
)- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๊ทธ์ฌ๋
์ด [ ๋ ]
isYouFollowMe
iuserMe
=๋ด ํ๋กํ : ๋
,๋ค๋ฅธ์ฌ๋ ํ๋กํ : ๊ทธ์ฌ๋
=${youIuser}
iuserYou
=๋ด ํ๋กํ : ๋
,๋ค๋ฅธ์ฌ๋ ํ๋กํ : ๋
=${meIuser}
- ๋ด๊ฐ ๋ค๋ฅธ์ฌ๋์ ํ๋ก์ฐํ(
iuserMe
)๊ฐฏ์๋ฅผ (iuserMe
๊ฐ [ ๋ ]์ ์ ์ฅ์์ [ ๋ค๋ฅธ์ฌ๋ ]๋ค์ ํ๋ก์ฐํ ๊ฒ์ด๋ค.)- ๋ดํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๋ด
๊ฐ [ ๋ ] ,๋ด
๊ฐ [ ๋ค๋ฅธ์ฌ๋ ]- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๊ทธ์ฌ๋
์ด [ ๋ ] ,๋ด
๊ฐ [ ๋ค๋ฅธ์ฌ๋ ]iuserMe
=${youIuser}
,iuserYou
=${meIuser}
- ๊ทธ๋์ ๋ดํ๋กํ์ ๋ค์ด๊ฐ ๋๋ ๋ฌด์กฐ๊ฑด
isYouFollowMe
๋ 0์ด ๋์ค๊ณ ,- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋ (
๊ทธ์ฌ๋
์ด [ ๋ ] ,๋ด
๊ฐ [ ๋ค๋ฅธ์ฌ๋ ])๊ทธ์ฌ๋
์ด๋
๋ฅผ ํ๋ก์ฐํ์ ๋๋ง 1์ด ๋์จ๋ค.
isMeFollowYou
- ๋ด๊ฐ ๋ค๋ฅธ์ฌ๋์ ํ๋ก์ฐํ(iuserMe) ๊ฐฏ์๋ฅผ (
iuserMe
๊ฐ [ ๋ ]์ ์ ์ฅ์์ [ ๋ค๋ฅธ์ฌ๋ ]๋ค์ ํ๋ก์ฐํ ๊ฒ์ด๋ค.)- ๋ด ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๋ด
๊ฐ [ ๋ ],๋ด
๊ฐ [ ๋ค๋ฅธ์ฌ๋ ]- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋
๋ด
๊ฐ [ ๋ ],๊ทธ์ฌ๋
์ด [ ๋ค๋ฅธ์ฌ๋ ]iuserMe
=${meIuser}
,iuserYou
=${youIuser}
- ๊ทธ๋์ ๋ด ํ๋กํ์ ๋ค์ด๊ฐ ๋๋ ๋ฌด์กฐ๊ฑด
isYouFollowMe
์isMeFollowYou
๋ 0์ด ๋์ค๊ณ- ๋ค๋ฅธ์ฌ๋ ํ๋กํ์ ๋ค์ด๊ฐ ๋๋ (
๋ด
๊ฐ [ ๋ ],๊ทธ์ฌ๋
์ด [ ๋ค๋ฅธ์ฌ๋ ])๋ด
๊ฐ๊ทธ์ฌ๋
์ ํ๋ก์ฐํ์ ๋๋ง 1์ด ๋์จ๋ค.
cntFollow
: ๋ด ํ๋กํ - ๋ด๊ฐ ํ๋ก์ฐ , ๋ค๋ฅธ์ฌ๋ ํ๋กํ - ๊ทธ์ฌ๋์ด ํ๋ก์ฐ (iuserMe
)
cntFollower
: ๋ดํ๋กํ - ๋๋ฅผ ํ๋ก์ฐ, ๋ค๋ฅธ์ฌ๋ ํ๋กํ - ๊ทธ์ฌ๋์ ํ๋ก์ฐ (iuserYou
)
isYouFollowMe
: ๋ค๋ฅธ์ฌ๋ ํ๋กํ - ๊ทธ์ฌ๋์ด ๋๋ฅผ ํ๋ก์ฐ (iuserMe
=${youIuser}
,iuserYou
=${meIuser}
)
isMeFollowYou
: ๋ค๋ฅธ์ฌ๋ ํ๋กํ - ๋ด๊ฐ ๊ทธ์ฌ๋์ ํ๋ก์ฐ (iuserMe
=${meIuser}
,iuserYou
=${youIuser}
)
table
CREATE TABLE t_user_follow (
iuserMe INT UNSIGNED,
iuserYou INT UNSIGNED,
regdt DATETIME DEFAULT NOW(),
PRIMARY KEY(iuserMe, iuserYou),
FOREIGN KEY (iuserMe) REFERENCES t_user(iuser),
FOREIGN KEY (iuserYou) REFERENCES t_user(iuser)
);
UserFollowEntity
public class UserFollowEntity {
private int iuserMe;
private int iuserYou;
private String regdt;
}
UserEntity
private int iuser;
private String provider;
private String email;
private String pw;
private String nm;
private String tel;
private String authCd;
private String mainProfile;
private String regdt;
UserDomain
public class UserDomain extends UserEntity {
private int cntFeed; //ํผ๋ ์นด์ดํธ
private int cntFollower; //ํ๋ก์ ์นด์ดํธ
private int cntFollow; //ํ๋ก์ฐ ์นด์ดํธ
private int isYouFollowMe; //๋๋ ๋๋ฅผ ํ๋ก์ฐ ํ๋
private int isMeFollowYou; //๋๋ ๋๋ฅผ ํ๋ก์ฐ ํ๋
}
UserDTO
public class UserDTO {
private int meIuser;
private int youIuser;
}
profile.html
<div id="localConst" th:attr="data-iuser=${profile.iuser}"></div>
<td th:unless="${auth.iuser eq profile.iuser}">
<th:block th:if="${profile.isMeFollowYou eq 1}">
<input type="button" class="instaBtn instaBtnEnable" id="btnFollow" data-follow="1" value="ํ๋ก์ฐ ์ทจ์">
</th:block>
<th:block th:unless="${profile.isMeFollowYou eq 1}">
<th:block th:if="${profile.isYouFollowMe eq 1}">
<input type="button" class="instaBtn" id="btnFollow" data-follow="0" value="๋งํ๋ก์ฐ">
</th:block>
<th:block th:unless="${profile.isYouFollowMe eq 1}">
<input type="button" class="instaBtn" id="btnFollow" data-follow="0" value="ํ๋ก์ฐ">
</th:block>
</th:block>
</td>
- ์๋๋ฐฉ์ ํ์ด์ง
- ๋ด๊ฐ ์ด ์ฌ๋์ ํ๋ก์ฐ ํ์ผ๋ฉด
ํ๋ก์ฐ ์ทจ์
๋ฒํผ.- ๋ด๊ฐ ์ด ์ฌ๋์ ํ๋ก์ฐ ํ์ง ์์์ผ๋ฉด
๋งํ๋ก์ฐ
๋ฒํผ. ๐ ๊ทผ๋ฐ ์๋๋ฐฉ์ ๋๋ฅผ ํ๋ก์ฐ ํ๋ค๋ฉดํ๋ก์ฐ
๋ฒํผ. ๐ ์๋๋ฐฉ๋ ๋๋ฅผ ํ๋ก์ฐ ํ์ง ์์๋ค๋ฉด
profile.js
const btnFollowElem = document.querySelector('#btnFollow'); //ํ๋ก์ฐ ๋ฒํผ
//ํ๋ก์ฐ ์ฒ๋ฆฌ
//type: 0 > ํ๋ก์ฐ ์ฒ๋ฆฌ
//type: 1 > ํ๋ก์ฐ ์ทจ์
function followProc(type, iuserYou, btnElem) {
const init = {};
const param = { iuserYou };
let queryString = '';
switch (type) {
case 0:
init.method = 'POST';
init.headers = { 'Content-Type': 'application/json' };
init.body = JSON.stringify(param);
break;
case 1:
init.method = 'DELETE';
queryString = `?iuserYou=${iuserYou}`;
break;
}
fetch('follow' + queryString, init)
.then(res => res.json())
.then(myJson => {
if(myJson.result === 1) {
let buttnNm = 'ํ๋ก์ฐ ์ทจ์';
if(btnElem.dataset.follow === '1') {
if(myJson.youFollowMe == null) { buttnNm = 'ํ๋ก์ฐ'; }
else { buttnNm = '๋งํ๋ก์ฐ'; }
}
btnElem.classList.toggle('instaBtnEnable');
btnElem.value = buttnNm;
btnElem.dataset.follow = 1 - btnElem.dataset.follow;
} else {
alert('์๋ฌ๊ฐ ๋ฐ์ํ์์ต๋๋ค.');
}
});
}
if(btnFollowElem) {
btnFollowElem.addEventListener('click', () => {
const follow = parseInt(btnFollowElem.dataset.follow);
const iuser = localConstElem.dataset.iuser;
followProc(follow, iuser, btnFollowElem);
});
}
UserController
@ResponseBody
@PostMapping("/follow")
public Map<String, Object> doFollow(@RequestBody UserFollowEntity param) {
return service.insUserFollow(param);
}
@ResponseBody
@DeleteMapping("/follow")
public Map<String, Object> cancelFollow(UserFollowEntity param) {
return service.delUserFollow(param);
}
UserFollowEntity
,iuserYou
: ๋ค๋ฅธ ์ฌ๋ ํ๋กํ(๊ทธ์ฌ๋)
UserService
//ํ๋ก์ฐ ํ๊ธฐ
public Map<String, Object> insUserFollow(UserFollowEntity param) {
param.setIuserMe(auth.getLoginUserPk());
Map<String, Object> res = new HashMap();
res.put(myConst.RESULT, mapper.insUserFollow(param));
return res;
}
//ํ๋ก์ฐ ์ทจ์
public Map<String, Object> delUserFollow(UserFollowEntity param) {
param.setIuserMe(auth.getLoginUserPk());
int result = mapper.delUserFollow(param);
Map<String, Object> res = new HashMap();
res.put(myConst.RESULT, result);
if(result == 1) {
UserFollowEntity param2 = new UserFollowEntity();
param2.setIuserMe(param.getIuserYou());
param2.setIuserYou(param.getIuserMe());
UserFollowEntity result2 = mapper.selUserFollow(param2);
res.put(myConst.YOU_FOLLOW_ME, result2);
}
return res;
}
insUserFollow
:
UserFollowEntity
,iuserYou
: ๋ค๋ฅธ ์ฌ๋ ํ๋กํ(๊ทธ์ฌ๋) ,iuserMe
: ๋- ๋ด๊ฐ ๊ทธ ์ฌ๋์ ํ๋ก์ฐ ํ๋ค.
Map<String, Object> res
:"result"
,0 ๋๋ 1
delUserFollow
:
UserFollowEntity
,iuserYou
: ๋ค๋ฅธ ์ฌ๋ ํ๋กํ(๊ทธ์ฌ๋) ,iuserMe
: ๋- ๋ด๊ฐ ๊ทธ ์ฌ๋์ ํ๋ก์ฐ ํ๋ค.
UserFollowEntity
,iuserYou
: ๋ ,iuserMe
: ๋ค๋ฅธ ์ฌ๋ ํ๋กํ(๊ทธ์ฌ๋)- ๊ทธ ์ฌ๋์ด ๋๋ฅผ ํ๋ก์ฐ ํ๋ค.
Map<String, Object> res
:
"result"
,0 ๋๋ 1
"youFollowMe"
,null ๋๋ UserFollowEntity(iuserYou : ๋ , iuserMe : ๋ค๋ฅธ ์ฌ๋ ํ๋กํ(๊ทธ์ฌ๋))
UserMapper
int insUserFollow(UserFollowEntity param);
UserFollowEntity selUserFollow(UserFollowEntity param);
int delUserFollow(UserFollowEntity param);
<insert id="insUserFollow">
INSERT INTO t_user_follow
( iuserMe, iuserYou )
VALUES
( ${iuserMe}, ${iuserYou} )
</insert>
<delete id="delUserFollow">
DELETE from t_user_follow
WHERE iuserMe = ${iuserMe} AND iuserYou = ${iuserYou}
</delete>
<select id="selUserFollow" resultType="UserFollowEntity">
SELECT iuserMe, iuserYou, regdt FROM t_user_follow
WHERE iuserMe = ${iuserMe}
AND iuserYou = ${iuserYou}
</select>
insUserFollow
:( ${iuserMe} : ๋ , ${iuserYou} : ๊ทธ์ฌ๋ )
delUserFollow
:( ${iuserMe} : ๋ , ${iuserYou} : ๊ทธ์ฌ๋ )
insUserFollow
:( ${iuserMe} : ๊ทธ์ฌ๋ , ${iuserYou} : ๋ )
header
์์ ๋๋ feed
์์ ํ๋กํ๊ฐ๊ธฐ
๋ฅผ ๋๋ฅธ๋ค.
/user/profile
/user/profile?iuser=${iuser}
๐ @controller
๋ด ํ๋กํ : UserDTO.youIuser
= ๋
๋ค๋ฅธ์ฌ๋ ํ๋กํ : UserDTO.youIuser
= ๊ทธ์ฌ๋
๐ @service
๋ด ํ๋กํ : UserDTO.meIuser
= ๋ , youIuser
= ๋
๋ค๋ฅธ์ฌ๋ ํ๋กํ : UserDTO.meIuser
= ๋ , youIuser
= ๊ทธ์ฌ๋
๐ @mapper
๋ด ํ๋กํ
UserDomain.๋์
iuser
, email
, nm
, tel
, mainProfile
, regdt
, cntFeed
, cntFollow
, cntFollower
isYouFollowMe(0)
, isMeFollowMe(0)
๋ค๋ฅธ์ฌ๋ ํ๋กํ
UserDomain.๊ทธ์ฌ๋์
iuser
, email
, nm
, tel
, mainProfile
, regdt
, cntFeed
, cntFollow
, cntFollower
isYouFollowMe
, isMeFollowMe
๐ @controller
"profile" , UserDomain
๐ profile.html
๐ profile.js
- ๋ด ํ๋กํ์ผ๊ฒฝ์ฐ ์ฌ๊ธฐ๋ก ์ฌ ์ ์๋ค.
btnFollowElem.dataset.follow
: 0(ํ๋ก์ฐ)
, 1(ํ๋ก์ฐ์ทจ์)
localConstElem.dataset.iuser
: profile.iuser(๊ทธ์ฌ๋)
followProc( follow, iuser, btnFollowElem)
follow (0-@Post /user/follow | 1-@Delete /user/follow)
iuser (profile.iuser(๊ทธ์ฌ๋) = UserFollowEntity.iuserYou)
ํ๋ก์ฐ์ฒ๋ฆฌ : "result" , 1
btnNm
= 'ํ๋ก์ฐ์ทจ์'classList
= instaBtn instaBtnEnable
dataset.follow
= 1
<input type="button" class="instaBtn" id="btnFollow" data-follow="0" value="(๋ง)ํ๋ก์ฐ">
<input type="button" class="instaBtn instaBtnEnable" id="btnFollow" data-follow="1" value="ํ๋ก์ฐ ์ทจ์">
ํ๋ก์ฐ์ทจ์์ฒ๋ฆฌ : "result" , 1
| "youFollowMe" , null ๋๋ UserFollowEntity(iuserMe ๊ทธ์ฌ๋ , iuserYou ๋)
btnNm
= 'ํ๋ก์ฐ์ทจ์' ๐ 'ํ๋ก์ฐ' | '๋งํ๋ก์ฐ'classList
= instaBtn
dataset.follow
= 0
<input type="button" class="instaBtn instaBtnEnable" id="btnFollow" data-follow="1" value="ํ๋ก์ฐ ์ทจ์">
<input type="button" class="instaBtn" id="btnFollow" data-follow="0" value="(๋ง)ํ๋ก์ฐ">
profile.html
<header th:fragment="header">
<span id="globalConst" sec:authorize="isAuthenticated()" th:with="auth=${#authentication.getPrincipal().getUser()}"
th:attr="data-iuser=${auth.iuser}, data-writer=${auth.nm}, data-writer-profile=${auth.mainProfile}"></span>
<div id="localConst" th:attr="data-iuser=${profile.iuser}"></div>
<td class="pointer follower">ํ๋ก์</td>
<td class="pointer follower" th:text="${profile.cntFollower}"></td>
<td class="pointer follow">ํ๋ก์ฐ</td>
<td class="pointer follow" th:text="${profile.cntFollow}"></td>
<div class="modal-follow hide">
<div>
<div class="container">
<div class="top">
<div id="title">ํ๋ก์ฐ</div>
<i id="modal-follow-close" class="moodal_clse fas fa-times"></i>
</div>
<div class="followCont"></div>
</div>
</div>
</div>
ํ๋ก์ฐ
,ํ๋ก์ฐ ์
๋๋ํ๋ก์
,ํ๋ก์ ์
๋ฅผ ๋๋ฅด๋ฉด ์ฌ์ฉ์๋ฆฌ์คํธ ๋ชจ๋ฌ์ฐฝ์ด ๋ฌ๋ค.
profile.js
const followerElemArr = document.querySelectorAll('.pointer.follower');
const followElemArr = document.querySelectorAll('.pointer.follow');
const modalFollowElem = document.querySelector('.modal-follow');
const modalFollowTitleElem = modalFollowElem.querySelector('#title');
const modalFollowCloseElem = document.querySelector('.modal-follow #modal-follow-close');
const modalFollowItemConElem = modalFollowElem.querySelector('.followCont');
if(followerElemArr) {
followerElemArr.forEach(item => {
item.addEventListener('click', () => {
modalFollowTitleElem.innerText = 'ํ๋ก์';
modalFollowElem.classList.remove('hide');
modalFollowItemConElem.innerHTML = '';
//ํ๋กํ ์ฌ์ฉ์๋ฅผ ํ๋ก์ฐํ ์ฌ๋๋ค ๋ฆฌ์คํธ
fetch(`getFollowerList?iuserYou=${localConstElem.dataset.iuser}`)
.then(res => res.json())
.then(myJson => {
if(myJson.length > 0) {
myJson.forEach(item => {
const cont = makeFollowItem(item);
modalFollowItemConElem.append(cont);
});
}
});
});
});
}
if(followElemArr) {
followElemArr.forEach(item => {
item.addEventListener('click', () => {
modalFollowTitleElem.innerText = 'ํ๋ก์ฐ';
modalFollowElem.classList.remove('hide');
modalFollowItemConElem.innerHTML = '';
//ํ๋กํ ์ฌ์ฉ์๊ฐ ํ๋ก์ฐํ ์ฌ๋๋ค ๋ฆฌ์คํธ
fetch(`getFollowList?iuserYou=${localConstElem.dataset.iuser}`)
.then(res => res.json())
.then(myJson => {
if(myJson.length > 0) {
myJson.forEach(item => {
const cont = makeFollowItem(item);
modalFollowItemConElem.append(cont);
});
}
});
});
});
}
if(modalFollowCloseElem) {
modalFollowCloseElem.addEventListener('click', () => {
modalFollowElem.classList.add('hide');
});
}
function makeFollowItem(item) {
const globalContElem = document.querySelector('#globalConst');
const loginIuser = globalContElem.dataset.iuser;
const cont = document.createElement('div');
cont.className = 'follow-item';
const img = document.createElement('img');
img.className = 'profile wh30 pointer';
img.src = `/pic/profile/${item.iuser}/${item.mainProfile}`;
img.onerror = () => { img.style.visibility = 'hidden'; }
img.addEventListener('click', ()=> {
moveToProfile(item.iuser); //feed.js ์ ์๋ ๋ฉ์๋
});
const nm = document.createElement('div');
const nmText = document.createElement('span');
nmText.innerText = item.nm;
nmText.className = 'pointer';
nmText.addEventListener('click', ()=> {
moveToProfile(item.iuser); //feed.js ์ ์๋ ๋ฉ์๋
});
nm.append(nmText);
const btn = document.createElement('input');
btn.className = 'instaBtn pointer';
btn.dataset.follow = '0';
btn.addEventListener('click', () => {
const follow = parseInt(btn.dataset.follow);
followProc(follow, item.iuser, btn);
});
cont.append(img);
cont.append(nm);
if(parseInt(loginIuser) !== item.iuser) {
btn.type = 'button';
if(item.isMeFollowYou) {
btn.dataset.follow = '1';
btn.value = 'ํ๋ก์ฐ ์ทจ์';
} else {
btn.classList.add('instaBtnEnable');
btn.value = 'ํ๋ก์ฐ';
}
cont.append(btn);
}
return cont;
}
followerElemArr
:<td class="pointer follower">ํ๋ก์</td><td class="pointer follower" th:text="${profile.cntFollower}"></td>
followElemArr
:<td class="pointer follow">ํ๋ก์ฐ</td><td class="pointer follow" th:text="${profile.cntFollow}"></td>
modalFollowElem
:<div class="modal-follow hide"> <div> <div class="container"> <div class="top"> <div id="title">ํ๋ก์ฐ</div> <i id="modal-follow-close" class="moodal_clse fas fa-times"></i> </div> <div class="followCont"></div> </div> </div> </div>
modalFollowTitleElem
:<div id="title">ํ๋ก์ฐ</div>
modalFollowCloseElem
:<i id="modal-follow-close" class="moodal_clse fas fa-times"></i>
modalFollowItemConElem
:<div class="followCont"></div>
UserController
@ResponseBody
@GetMapping("/getFollowerList")
public List<UserDomain> getFollowerList(UserFollowEntity param) {
return service.selUserFollowerList(param);
}
@ResponseBody
@GetMapping("/getFollowList")
public List<UserDomain> getFollowList(UserFollowEntity param) {
return service.selUserFollowList(param);
}
UserService
public List<UserDomain> selUserFollowerList(UserFollowEntity param) {
param.setIuserMe(auth.getLoginUserPk());
return mapper.selUserFollowerList(param);
}
public List<UserDomain> selUserFollowList(UserFollowEntity param) {
param.setIuserMe(auth.getLoginUserPk());
return mapper.selUserFollowList(param);
}
UserMapper
List<UserDomain> selUserFollowerList(UserFollowEntity param);
List<UserDomain> selUserFollowList(UserFollowEntity param);
<select id="selUserFollowerList" resultType="UserDomain">
SELECT B.iuser, B.nm, B.mainProfile
, CASE WHEN C.iuserMe IS NULL THEN 0 ELSE 1 END AS isMeFollowYou
FROM t_user_follow A
INNER JOIN t_user B
ON A.iuserMe = B.iuser
LEFT JOIN t_user_follow C
ON C.iuserMe = ${iuserMe} -- ๋ก๊ทธ์ธํ ์ฌ๋ pk
AND C.iuserYou = A.iuserMe
WHERE A.iuserYou = ${iuserYou} -- ํ๋กํ ์ฃผ์ธ์ฅ pk
</select>
<select id="selUserFollowList" resultType="UserDomain">
SELECT B.iuser, B.nm, B.mainProfile
, CASE WHEN C.iuserMe IS NULL THEN 0 ELSE 1 END AS isMeFollowYou
FROM t_user_follow A
INNER JOIN t_user B
ON A.iuserYou = B.iuser
LEFT JOIN t_user_follow C
ON C.iuserMe = ${iuserMe} -- ๋ก๊ทธ์ธํ ์ฌ๋ pk
AND C.iuserYou = A.iuserYou
WHERE A.iuserMe = ${iuserYou} -- ํ๋กํ ์ฃผ์ธ์ฅ pk
</select>
profile.js
followerElemArr.forEach(item => { item.addEventListener('click', () => {})});
getFollowList?iuserYou=${localConstElem.dataset.iuser}
${localConstElem.dataset.iuser}
=${profile.iuser}
๐ [ ๋ ] ๋๋ [ ๊ทธ์ฌ๋ ]์ iuser
๐
UserController. getFollowerList()
@ResponseBody
@GetMapping("/getFollowerList")
public List<UserDomain> getFollowerList(UserFollowEntity param) {
return service.selUserFollowerList(param);
}
UserFollowEntity.iuserYou(๊ทธ์ฌ๋ ๋๋ ๋)
๐
UserService.selUserFollowerList()
public List<UserDomain> selUserFollowerList(UserFollowEntity param) {
param.setIuserMe(auth.getLoginUserPk());
return mapper.selUserFollowerList(param);
}
UserFollowEntity.iuserYou(๊ทธ์ฌ๋ ๋๋ ๋) | iuserMe(๋)
๐
UserMapper.selUserFollowerList()
<select id="selUserFollowerList" resultType="UserDomain">
SELECT B.iuser, B.nm, B.mainProfile
, CASE WHEN C.iuserMe IS NULL THEN 0 ELSE 1 END AS isMeFollowYou
FROM t_user_follow A
INNER JOIN t_user B
ON A.iuserMe = B.iuser
LEFT JOIN t_user_follow C
ON C.iuserMe = ${iuserMe} -- ๋ก๊ทธ์ธํ ์ฌ๋ pk
AND C.iuserYou = A.iuserMe
WHERE A.iuserYou = ${iuserYou} -- ํ๋กํ ์ฃผ์ธ์ฅ pk
</select>
iuserMe
๊ฐ [ ๋ ]์ ์ ์ฅ์์ [ ๋ค๋ฅธ์ฌ๋ ]์ ํ๋ก์ฐ ํ ๊ฒ์ด๋ค.A.iuserMe
=B.iuser
๋A.iuserYou
=${iuserYou}
: [๊ทธ์ฌ๋ ๋๋ ๋]๋ฅผ ํ๋ก์ฐํ ์ฌ๋๋ค์ด๋ค.C.iuserMe
=${iuserMe}
: [ ๋ ]- ์ฆ,
C.iuserMe
=${iuserMe}
[ ๋ ]์ธ๋ฐ,A.iuserYou
=${iuserYou}
[ ๊ทธ ์ฌ๋ ๋๋ ๋ ]๋ฅผ ํ๋ก์ฐํ๋A.iuserMe
=B.iuser
=C.iuserYou
๋ฅผ ํ๋ก์ฐํ๋ ์ง ์์๋ณด๋ ๊ฒ์ด๋ค.
๐
profile.js
makeFollowItem(item)
item
: [ ๊ทธ์ฌ๋ ๋๋ ๋ ]๋ฅผ ํ๋ก์ฐํ๋ ์ฌ๋์iuser, nm, mainprofile
,iuserMe
([ ๋ด ] ๊ฐ [๊ทธ์ฌ๋ ๋๋ ๋]๋ฅผ ํ๋ก์ฐํ๋ ์ฌ๋์ ํ๋ก์ฐํ๋์ง)
const globalContElem = document.querySelector('#globalConst');
const loginIuser = globalContElem.dataset.iuser;
globalContElem
:<span id="globalConst" sec:authorize="isAuthenticated()" th:with="auth=${#authentication.getPrincipal().getUser()}" th:attr="data-iuser=${auth.iuser}, data-writer=${auth.nm}, data-writer-profile=${auth.mainProfile}"></span>
loginIuser
: [ ๋ ]
const cont = document.createElement('div');
cont.className = 'follow-item';
<div class="follow-item"></div>
const img = document.createElement('img');
img.className = 'profile wh30 pointer';
img.src = `/pic/profile/${item.iuser}/${item.mainProfile}`;
img.onerror = () => { img.style.visibility = 'hidden'; }
img.addEventListener('click', ()=> {
moveToProfile(item.iuser); //feed.js ์ ์๋ ๋ฉ์๋
});
<img class="profile wh30 pointer" src="/pic/profile/${item.iuser}/${item.mainProfile}">
const nm = document.createElement('div');
const nmText = document.createElement('span');
nmText.innerText = item.nm;
nmText.className = 'pointer';
nmText.addEventListener('click', ()=> {
moveToProfile(item.iuser); //feed.js ์ ์๋ ๋ฉ์๋
});
nm.append(nmText);
<div> <span class="pointer" onclick="moveToProfile(item.iuser)">item.nm</span> </div>
const btn = document.createElement('input');
btn.type = 'button';
btn.className = 'instaBtn pointer';
btn.dataset.follow = '0';
btn.addEventListener('click', () => {
const follow = parseInt(btn.dataset.follow);
followProc(follow, item.iuser, btn);
});
<input type="button" class="instaBtn pointer" data-follow="0">
cont.append(img);
cont.append(nm);
<div class="follow-item"> <img class="profile wh30 pointer" src="/pic/profile/${item.iuser}/${item.mainProfile}" onerror="" onclick="moveToProfile(item.iuser)"> <div> <span class="pointer" onclick="moveToProfile(item.iuser)">item.nm</span> </div> </div>
if(parseInt(loginIuser) !== item.iuser) {
if(item.isMeFollowYou) {
btn.classList.add('instaBtnEnable');
btn.dataset.follow = '1';
btn.value = 'ํ๋ก์ฐ ์ทจ์';
} else {
btn.value = 'ํ๋ก์ฐ';
}
cont.append(btn);
}
return cont;
}
if(parseInt(loginIuser) !== item.iuser)
: [ ๋ ] ์ [ ๋ ๋๋ ๊ทธ์ฌ๋ ]์ ํ๋ก์ฐํ๋ ์ฌ๋์ด ๊ฒน์น๋ค๋ฉด ,
์ฆ, [ ๊ทธ ์ฌ๋ ]์ ํ๋ก์ฐํ๋ ์ฌ๋ ์ค์ [ ๋ด ]๊ฐ ์๋ค๋ฉดํ๋ก์ฐ ๋ฒํผ
์ ๋ฃ์ง ์๊ฒ ๋ค.
<div class="follow-item"> <img class="profile wh30 pointer" src="/pic/profile/${item.iuser}/${item.mainProfile}" onerror="" onclick="moveToProfile(item.iuser)"> <div> <span class="pointer" onclick="moveToProfile(item.iuser)">item.nm</span> </div> <input type="button" class="instaBtn pointer" data-follow="0" value="ํ๋ก์ฐ" onclick=" followProc(follow, item.iuser, btn);"> <input type="button" class="instaBtn instaBtnEnable pointer" data-follow="1" value="ํ๋ก์ฐ ์ทจ์" onclick=" followProc(follow, item.iuser, btn);"> </div>
๐
profile.js
followerElemArr.forEach(item => { item.addEventListener('click', () => {})});
........
modalFollowTitleElem.innerText = 'ํ๋ก์';
modalFollowElem.classList.remove('hide');
modalFollowItemConElem.innerHTML = '';
........
.then(myJson => {
if(myJson.length > 0) {
myJson.forEach(item => {
const cont = makeFollowItem(item);
modalFollowItemConElem.append(cont);
});
}
๐ ๊ฒฐ๊ณผ
<div class="modal-follow">
<div>
<div class="container">
<div class="top">
<div id="title">ํ๋ก์</div>
<i id="modal-follow-close" class="moodal_clse fas fa-times"></i>
</div>
<div class="followCont">
<div class="follow-item">
<img class="profile wh30 pointer" src="/pic/profile/${item.iuser}/${item.mainProfile}"
onerror="" onclick="moveToProfile(item.iuser)">
<div>
<span class="pointer" onclick="moveToProfile(item.iuser)">item.nm</span>
</div>
<input type="button" class="instaBtn pointer" data-follow="0"
value="ํ๋ก์ฐ" onclick=" followProc(follow, item.iuser, btn);">
<input type="button" class="instaBtn instaBtnEnable pointer" data-follow="1"
value="ํ๋ก์ฐ ์ทจ์" onclick=" followProc(follow, item.iuser, btn);">
</div>
</div>
</div>
</div>
</div>