본문 바로가기
프로젝트

게시글 좋아요 기능 만들기

by 해룸 2024. 2. 13.
model Likes {
  id        Int         @id @default(autoincrement()) @map("id")
  userId    Int         @map("userId")
  postId    Int         @map("postId")

  users Users @relation(fields:[userId] , references: [id] , onDelete: Cascade)
  posts Posts @relation(fields:[postId] , references: [id] , onDelete: Cascade)

  @@map("Likes")
}

Likes 테이블의 스키마는 이렇다!

userId 와 postId 를 가지고 있고, 로그인 한 유저가 해당 포스트에 "좋아요" 요청을 보내면 id에 저장이 된다.

 

//좋아요
router.post('/like/:postId', authMiddleWare, async (req, res, next) => {
	try {
		const { postId } = req.params;
		const { id } = req.user;

		const Findpost = await prisma.posts.findFirst({
			where: { id: +postId },
			select: {
				userId: true,
				parentsId: true,
			},
		});

		if (!Findpost) {
			return res
				.status(404)
				.json({ message: '해당 게시글이 존재 하지 않습니다.' });
		}

		//내 게시글은 좋아요 안되게 => 해당 포스트 작성자 아이디와 req.user id가 일치할 경우 안되게
		if (Findpost.userId == +id) {
			return res
				.status(403)
				.json({ message: '자신이 쓴 게시글은 좋아요를 누를 수 없습니다!!!' });
		}
		//아이디에 해당하는 포스트를 찾아서,
		//인증된 유저 정보가 해당 포스트에 좋아요 기록이 없다면 좋아요, 있다면 좋아요 취소
		const like = await prisma.likes.findFirst({
			where: { userId: +id, postId: +postId },
		});

		if (!like) {
			await prisma.likes.create({
				data: {
					userId: +id,
					postId: +postId,
				},
			});

			const undatedParentsId = Findpost.parentsId + 1;
			console.log(Findpost.parentsId, undatedParentsId);
			await prisma.posts.update({
				where: {
					id: +postId,
				},
				data: {
					parentsId: undatedParentsId,
				},
			});
		} else {
			return res
				.status(403)
				.json({ message: '좋아요는 한번만 누를 수 있습니다.' });
		}

		return res.status(201).json({ message: '좋아용' });
	} catch (err) {
		next(err);
	}
});

like 기록이 없다면 posts 테이블의 요소인 parentsId(여기에 좋아요수를 저장한다.)에 +1을 해준다.

 

//좋아요취소
router.delete('/like/:postId', authMiddleWare, async (req, res, next) => {
	try {
		const { postId } = req.params;
		const { id } = req.user;

		const Findpost = await prisma.posts.findFirst({
			where: { id: +postId },
		});

		if (!Findpost) {
			return res
				.status(404)
				.json({ message: '해당 게시글이 존재 하지 않습니다.' });
		}

		const like = await prisma.likes.findFirst({
			where: { userId: +id, postId: +postId },
		});
		if (like) {
			await prisma.likes.delete({
				where: { id: like.id },
			});
			const undatedParentsId = Findpost.parentsId - 1;
			await prisma.posts.update({
				where: {
					id: +postId,
				},
				data: {
					parentsId: undatedParentsId,
				},
			});
		} else {
			return res.status(404).json({ message: '좋아요 기록이 없습니다.' });
		}
		return res.status(200).json({ message: '싫어요' });
	} catch (err) {
		next(err);
	}
});

원래는 좋아요 취소 기능도 좋아요에 함께 넣으려고 했다. 만약 좋아요 한 기록이 있다면 좋아요 취소가 되는 식으로?

그런데 RESTful한 API를 위해 이런식으로 따로 api를 만들었는데 이게 맞는지는 잘 모르겠다.

마찬가지로 좋아요한 기록이 있다면 parentsId에서 -1을 하고, 좋아요 취소를 하도록 한다.

 

//좋아요 받은 글 최신순으로 표시(첫화면)
router.get('/postlike', async (req, res, next) => {
	//좋아요 받은 글 찾아서 최신순으로표시
	try {
		const postlike = await prisma.posts.findMany({
			where: {
				parentsId: {
					gt: 0, //좋아요 수가 0초과인 것만 가져오기
				},
			},
			select: {
				id: true,
				title: true,
				content: true,
				parentsId: true,
				createdAt: true,
			},
			orderBy: {
				createdAt: 'desc',
			},
		});

		//표시할 글이 없을 경우 최신순으로 게시글 조회
		if (postlike.length === 0) {
			const post = await prisma.posts.findMany({
				select: {
					id: true,
					title: true,
					content: true,
					parentsId: true,
					createdAt: true,
				},
				orderBy: {
					createdAt: 'desc',
				},
			});
			return res.status(200).json({ data: post });
		}

		return res.status(200).json({ data: postlike });
	} catch (err) {
		next(err);
	}
});

프론트작업을 위해 만든 api.

메인화면에 좋아요 받은 게시글들을 최신순으로 표시하도록 해준다.