차단, 차단풀기(팔로우, 언팔로우와 동일)

개발공부·2022년 12월 26일
0

* 결과

{ id : 1 name: hello }
{ id : 2 name: test }
{ id : 3 name: hi }
{ id : 4 name: good }

1) hello(1)가 test(2)를 차단한 경우

▶ "팔로워" 목록에서 빠지고 "차단한 사람" 목록에 추가됨
▶ 닉네임 옆에 차단한 사람이란 표시가 뜸

2) hello(1)가 test(2)를 차단 해제 하는 경우

▶ "차단한 사람" 목록에서 빠지고 "팔로워" 목록에 추가됨
▶ 닉네임 옆에 팔로우/언팔로우 표시가 뜸

3) hello(1)가 good(4)에게 차단 당한 경우

▶ good은 hello와 팔로잉 관계일 땐 차단 할 수 없음
-> 언팔로우 한 뒤 차단해야 함
▶ hello는 good의 글을 보지 못함

* 핵심

내가(로그인 한 경우) 차단한 리스트 : Blockings
내가(로그인 한 경우) 차단 당한 리스트 : Blockeds

  • 내가 차단하면 Blockings 리스트에 들어가고 동시에 followers가 줄어듦
    반대로 내가 차단 당하면 Blockeds에 들어감

  • 차단은 axios.post, 차단을 푸는 건 axios.delete

* 코드

* Front Redux, components

[userSaga.js]

function blockFollowAPI(data) { //차단하는 api
  return axios.post(`/user/block/${data}`);
}

function* blockFollow(action) {
  try {
    const data = action.payload;
    const result = yield call(blockFollowAPI, data);
    yield put(blockfollowSuccess(result.data));
  } catch (error) {
    yield put(blockfollowFailure(error));
    console.log(error);
  }
}

function loadBlockingAPI(data) { 
  return axios.get("/user/blockings", data);
}

//load가 있어야 정보를 불러옴

function* loadBlocking(action) { 
  try {
    const data = action.payload;
    const result = yield call(loadBlockingAPI, data);
    yield put(loadBlockingSuccess(result.data));
  } catch (error) {
    yield put(loadBlockingFailure(error));
    console.log(error);
  }
}

function loadBlockedAPI(data) {
  return axios.get("/user/blockeds", data);
}

function* loadBlocked(action) {
  try {
    const data = action.payload;
    const result = yield call(loadBlockedAPI, data);
    yield put(loadBlockedSuccess(result.data));
  } catch (error) {
    yield put(loadBlockedFailure(error));
    console.log(error);
  }
}

function cancleBlockAPI(data) { //차단 해제 api
  return axios.delete(`/user/${data}/block`, data);
}

function* cancleBlock(action) {
  try {
    const data = action.payload;
    const result = yield call(cancleBlockAPI, data);
    yield put(cancleBlockSuccess(result.data));
  } catch (error) {
    yield put(cancleBlockFailure(error));
    console.log(error);
  }
}

[userSlice.js]

  blockfollowSuccess: (state, action) => {
      const data = action.payload;
      console.log("data.blockingUser", data.blockingUser);
      console.log("data.blockedUser", data.blockedUser);
      state.blockfollowLoading = false;
      state.blockfollowComplete = true;
      //내 팔로워 목록에서 줄어들음
      state.me.Followers = state.me.Followers.filter(
        (v) => v.id !== data.blockingUser
      );
      //내가 차단한 경우
      state.me.Blockeds.push({ id: data.blockingUser });

      //내가 차단된 경우
      state.me.Blockings.push({ id: data.blockedUser });
    },
    
    loadBlockingSuccess: (state, action) => {
      const data = action.payload;
      state.loadBlockingLoading = false;
      state.loadBlockingComplete = true;
      state.me.Blockings = data;
    },
     loadBlockedSuccess: (state, action) => {
      const data = action.payload;
      state.loadBlockedLoading = false;
      state.loadBlockedComplete = true;
      state.me.Blockeds = data;
    },
    
     cancleBlockSuccess: (state, action) => {
      const data = action.payload;
      console.log("data", data);
      state.cancleBlockLoading = false;
      state.cancleBlockComplete = true;
      state.me.Blockings = state.me.Blockings.filter(
        (v) => v.id !== data.UserId
      );
      state.me.Followers.push({ id: data.UserId });
    },

[components/PostCard.js]

import {
  followRequest,
  loadBlockingRequest,
  loadBlockedRequest,
  unfollowRequest,
} from "../../redux/feature/userSlice";

//me 정보는 부모인 pages/post.js에서 받아오는 props

 const blockingLists = me?.Blockings; 
  const blockedLists = me?.Blockeds;

  useEffect(() => {
    if (me) {
      dispatch(loadBlockedRequest());
      dispatch(loadBlockingRequest());
      dispatch(loadBlockedRequest());
    }
  }, []);
  
  return (
  
  //(내가 차단했을 때 영향) 닉네임 옆의 차단한 유저, 언팔로우, 팔로우
    {id === undefined ? null : blockingLists &&
                blockingLists?.find((block) => block.id === post.UserId) ? (
                <div className="ml-2 bg-gray-100 rounded w-20">차단한 유저</div>
              ) : (
                <button
                  onClick={onClickFollow}
                  className={`ml-2 ${
                    isFollowing ? "bg-red-500" : "bg-light-green"
                  } rounded w-20 text-white ${
                    isFollowing
                      ? "hover:bg-light-beige hover:text-red-500"
                      : "hover:bg-light-beige hover:text-light-green"
                  }  `}
                >
                  {id === post.UserId ? null : (
                    <p className="text-sm">
                      {isFollowing ? "언팔로우" : "팔로우"}
                    </p>
                  )}
                </button>
              )}
              
   //(내가 차단됬을 때 영향) 글쓰기 내용
   
    {id === undefined ? ( //로그인하지 않았을 땐 모든 내용이 보임
            <PostCardContent
              editMode={editMode}
              onCancleRevisePost={onCancleRevisePost}
              onRevisePost={onRevisePost}
              image={post?.Images}
              content={post.content}
              index={index}
            />
          ) : null}

          {blockedLists &&
          blockedLists.find((block) => block.id === post.UserId) ? (
            <p className="ml-3 p-2 text-red-500">게시글을 볼 수 없습니다.</p>
          ) : (
            <PostCardContent
              editMode={editMode}
              onCancleRevisePost={onCancleRevisePost}
              onRevisePost={onRevisePost}
              image={post?.Images}
              content={post.content}
              index={index}
            />
          )}
  )

* Backend API

[model/user.js]

db.User.belongsToMany(db.User, {
      through: "BlockFollow",
      as: "Blockeds",
      foreignKey: "BlockingId",
    });
    db.User.belongsToMany(db.User, {
      through: "BlockFollow",
      as: "Blockings",
      foreignKey: "BlockedId",
    });

[routes/user.js]

router.get("/", async (req, res, next) => { //me 값에 block값들도 포함
  // GET /user
  try {
    if (req.user) {
      const fullUserWithoutPassword = await User.findOne({
        where: { id: req.user.id },
        attributes: {
          exclude: ["password"],
        },
        include: [
          {
            model: Post,
            attributes: ["id"],
          },
          {
            model: User,
            as: "Followings",
            attributes: ["id"],
          },
          {
            model: User,
            as: "Blockings",
            attributes: ["id"],
          },
          {
            model: User,
            as: "Followers",
            attributes: ["id"],
          },
          {
            model: User,
            as: "Blockeds",
            attributes: ["id"],
          },
        ],
      });
      res.status(200).json(fullUserWithoutPassword);
    } else {
      res.status(200).json(null);
    }
  } catch (error) {
    console.error(error);
    next(error);
  }
});

router.post("/block/:userId", isLoggedIn, async (req, res, next) => {
  // post /user/block/2
  try {
    const user = await User.findOne({ where: { id: req.user.id } });
    if (!user) {
      res.status(403).send("로그인이 필요합니다.");
    }
    await user.removeFollowers(req.params.userId);
    await user.addBlocking(req.params.userId);
    res.status(200).json({
      blockedUser: parseInt(req.user.id),
      blockingUser: parseInt(req.params.userId, 10),
    });
  } catch (error) {
    console.error(error);
    next(error);
  }
});

router.delete("/:userId/block", isLoggedIn, async (req, res, next) => {
  // DELETE /user/1/block
  try {
    const user = await User.findOne({ where: { id: req.user.id } });
    if (!user) {
      res.status(403).send("없는 사람을 차단해제 하려고 하시네요?");
    }
    await user.removeBlockings(req.params.userId);
    await user.addFollowers(req.params.userId);
    res.status(200).json({ UserId: parseInt(req.params.userId, 10) });
  } catch (error) {
    console.error(error);
    next(error);
  }
});
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글