From 11e4dba860e46640556850b93dfb9ee24c00e2fc Mon Sep 17 00:00:00 2001
From: nnyouung <104901660+nnyouung@users.noreply.github.com>
Date: Mon, 22 Jul 2024 01:53:23 +0900
Subject: [PATCH] Feat/backend integration bookmark (#83)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: 북마크 생성 백엔드 연결 및 변수명 직관적으로 변경
수정사항
- 북마크 생성 백엔드 연결
- api.js의 좋아요 생성 변수명 변경 (postHeart -> createLike)
- PostPage의 handleHeart <-> handleHeart 변수명 변경
* feat: 좋아요 및 북마크한 게시물의 색상 변화가 유지되도록 수정
수정사항
- 사용자가 좋아요 및 북마크한 게시물의 색상 변화, 즉 상태가 유지되도록 수정
* fix: 서버 데이터 구조 변경에 따른 북마크한 글 조회 오류 수정
수정사항
- 모든 북마크 조회 api 서버 데이터 구조가 바뀜에 따라, 북마크한 글 조회를 할 수 있게 조건부로 수정
* style: Prettier & ESLint 적용
---
src/components/community/IconBookmark.jsx | 38 +++---
src/components/community/ItemComment.jsx | 6 +-
src/components/member/ItemLikeBookmark.jsx | 12 +-
src/config/api.js | 12 +-
src/pages/community/PostPage.jsx | 139 ++++++++++++++++-----
src/pages/member/BookmarkPostPage.jsx | 6 +-
6 files changed, 155 insertions(+), 58 deletions(-)
diff --git a/src/components/community/IconBookmark.jsx b/src/components/community/IconBookmark.jsx
index 4b0feedf..2129dc21 100644
--- a/src/components/community/IconBookmark.jsx
+++ b/src/components/community/IconBookmark.jsx
@@ -1,20 +1,26 @@
import * as React from "react";
import Svg, { Path } from "react-native-svg";
-const IconBookmark = (props) => (
-
-);
+import { CustomTheme } from "@styles/CustomTheme";
+
+const IconBookmark = ({ props, active }) => {
+ const color = active ? CustomTheme.pointYellow : CustomTheme.borderColor;
+ return (
+
+ );
+};
+
export default IconBookmark;
diff --git a/src/components/community/ItemComment.jsx b/src/components/community/ItemComment.jsx
index b1dfa24d..4f04ba4f 100644
--- a/src/components/community/ItemComment.jsx
+++ b/src/components/community/ItemComment.jsx
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import { View, Text, StyleSheet, TouchableOpacity, Alert } from "react-native";
import { CustomTheme } from "@styles/CustomTheme";
-import { postHeart } from "config/api";
+import { createLike } from "config/api";
import IconHeart from "@components/community/IconHeart";
import IconBookmark from "@components/community/IconBookmark";
@@ -32,7 +32,7 @@ const ItemComment = ({ props, id }) => {
const heartCommentAlert = async (commentId) => {
try {
- await postHeart("COMMENT", id, commentId);
+ await createLike("COMMENT", id, commentId);
console.log("댓글 좋아요 성공");
} catch (error) {
console.error(
@@ -125,7 +125,7 @@ const ItemComment = ({ props, id }) => {
- {date(post.created)}
+ {date(post.date)}
diff --git a/src/components/member/ItemLikeBookmark.jsx b/src/components/member/ItemLikeBookmark.jsx
index ce378b0a..73777c61 100644
--- a/src/components/member/ItemLikeBookmark.jsx
+++ b/src/components/member/ItemLikeBookmark.jsx
@@ -6,7 +6,7 @@ import { CustomTheme } from "@styles/CustomTheme";
const { fontCaption, fontNavi } = CustomTheme;
-const ItemLikeBookmark = ({ props }) => {
+const ItemLikeBookmark = ({ props, type = "like" }) => {
const navigation = useNavigation();
return (
@@ -27,7 +27,7 @@ const ItemLikeBookmark = ({ props }) => {
post.image ? { width: 196 } : {},
]}
>
- {post.title}
+ {type === "like" ? post.title : post.post.title}
{
post.image ? { width: 196 } : {},
]}
>
- {post.content}
+ {type === "like"
+ ? post.content
+ : post.post.content}
@@ -55,10 +57,10 @@ const ItemLikeBookmark = ({ props }) => {
const styles = StyleSheet.create({
ItemCommunity: {
width: "100%",
- height: 78,
+ height: 62,
backgroundColor: CustomTheme.bgBasic,
borderRadius: 20,
- borderWidth: 2,
+ borderWidth: 3,
borderColor: CustomTheme.primaryBg,
paddingHorizontal: 20,
justifyContent: "center",
diff --git a/src/config/api.js b/src/config/api.js
index ff7e2af2..3c09decd 100644
--- a/src/config/api.js
+++ b/src/config/api.js
@@ -139,10 +139,18 @@ export const getCommentById = (id) => {
return api.get(`comments/${id}`);
};
-export const postHeart = (type, id, commentId) => {
+export const createLike = (type, postId, commentId) => {
return api.post("/likes", {
type: type,
- postId: id,
+ postId: postId,
commentId: commentId,
});
};
+
+export const createBookmark = (chatroomId, chatId, postId) => {
+ return api.post("/bookmarks", {
+ chatroomId: chatroomId,
+ chatId: chatId,
+ postId: postId,
+ });
+};
diff --git a/src/pages/community/PostPage.jsx b/src/pages/community/PostPage.jsx
index 341e7bff..85dc48a4 100644
--- a/src/pages/community/PostPage.jsx
+++ b/src/pages/community/PostPage.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import {
TouchableOpacity,
Text,
@@ -12,16 +12,19 @@ import {
Alert,
} from "react-native";
import { useFocusEffect } from "@react-navigation/native";
-import * as SecureStore from "expo-secure-store";
import PostStyles from "@pages/community/PostStyles";
import { CustomTheme } from "@styles/CustomTheme";
+import { useOnboarding } from "src/states/OnboardingContext.js";
import { usePostModify } from "src/states/PostModifyContext";
import {
getPostById,
getCommentById,
postCommentSend,
- postHeart,
+ createLike,
+ createBookmark,
+ getLikedPost,
+ getBookmarkPost,
} from "config/api";
import TopBar from "@components/common/TopBar";
@@ -39,6 +42,7 @@ const PostPage = ({ route }) => {
const [modalVisible, setModalVisible] = useState(false);
const { id } = route.params;
+ const { onboardingData } = useOnboarding();
const { updatePostModifyData } = usePostModify();
const [title, setTitle] = useState("");
@@ -70,31 +74,28 @@ const PostPage = ({ route }) => {
const postComment = async () => {
try {
const postByIdResponse = await getPostById(id);
- const postData = postByIdResponse.data;
- setTitle(postData.title);
- setContext(postData.content);
- setHeart(postData.likesCount);
- setBookmark(postData.bookmarkCount);
- setCreated(date(postData.created));
- setIsPublic(postData.isPublic);
-
- if (postData.isPublic === false) {
- setWriterName(postData.writer.username);
- } else if (postData.isPublic === true) {
+ setTitle(postByIdResponse.data.title);
+ setContext(postByIdResponse.data.content);
+ setHeart(postByIdResponse.data.likesCount);
+ setBookmark(postByIdResponse.data.bookmarkCount);
+ setCreated(date(postByIdResponse.data.created));
+ setIsPublic(postByIdResponse.data.isPublic);
+
+ if (postByIdResponse.data.isPublic === false) {
+ setWriterName(postByIdResponse.data.writer.username);
+ } else if (postByIdResponse.data.isPublic === true) {
setWriterName("익명");
}
- const memberId =
- await SecureStore.getItemAsync("member_id");
- if (memberId === postData.writer.id) {
+ if (onboardingData.id === postByIdResponse.data.writer.id) {
setIsMe(true);
updatePostModifyData({
- memberId: postData.writer.id,
+ memberId: postByIdResponse.data.writer.id,
id: id,
- title: postData.title,
- context: postData.content,
- boardType: postData.boardType,
- isPublic: postData.isPublic,
+ title: postByIdResponse.data.title,
+ context: postByIdResponse.data.content,
+ boardType: postByIdResponse.data.boardType,
+ isPublic: postByIdResponse.data.isPublic,
});
}
@@ -104,7 +105,11 @@ const PostPage = ({ route }) => {
console.log("게시글 및 댓글 조회 성공");
} catch (error) {
console.error(
- "게시글 및 댓글 조회 오류:",
+ "게시글 조회 오류:",
+ error.response ? error.response.data : error.message,
+ );
+ console.error(
+ "댓글 조회 오류:",
error.response ? error.response.data : error.message,
);
}
@@ -173,9 +178,9 @@ const PostPage = ({ route }) => {
const [pressHeart, setPressHeart] = useState();
- const heartAlert = async () => {
+ const handleHeart = async () => {
try {
- await postHeart("POST", id);
+ await createLike("POST", id);
console.log("게시글 좋아요 성공");
} catch (error) {
console.error(
@@ -187,7 +192,7 @@ const PostPage = ({ route }) => {
}
};
- const handleHeart = () => {
+ const heartAlert = () => {
Alert.alert(
"",
"이 게시물에 좋아요를 누르시겠습니까?",
@@ -201,7 +206,58 @@ const PostPage = ({ route }) => {
onPress: () => {
setHeart((prevHeart) => prevHeart + 1);
setPressHeart(true);
- heartAlert();
+ handleHeart();
+ },
+ },
+ ],
+ { cancelable: false },
+ );
+ };
+
+ const likedPosts = async () => {
+ try {
+ const response = await getLikedPost();
+ const likedPostIdList = response.data.map((item) => item.id);
+ setPressHeart(likedPostIdList.includes(id));
+ } catch (error) {
+ console.error(
+ "좋아요 상태 조회 실패:",
+ error.response ? error.response.data : error.message,
+ );
+ }
+ };
+
+ const [pressBookmark, setPressBookmark] = useState();
+
+ const handleBookmark = async () => {
+ try {
+ await createBookmark(null, null, id);
+ console.log("게시글 북마크 성공");
+ } catch (error) {
+ console.error(
+ "게시글 북마크 실패:",
+ error.response ? error.response.data : error.message,
+ );
+ setBookmark((prevBookmark) => prevBookmark - 1);
+ setPressBookmark(false);
+ }
+ };
+
+ const bookmarkAlert = () => {
+ Alert.alert(
+ "",
+ "이 게시물을 북마크하시겠습니까?",
+ [
+ {
+ text: "취소",
+ style: "cancel",
+ },
+ {
+ text: "확인",
+ onPress: () => {
+ setBookmark((prevBookmark) => prevBookmark + 1);
+ setPressBookmark(true);
+ handleBookmark();
},
},
],
@@ -209,6 +265,24 @@ const PostPage = ({ route }) => {
);
};
+ const bookmarkedPosts = async () => {
+ try {
+ const response = await getBookmarkPost();
+ const bookmarkedPostIdList = response.data.map((item) => item.id);
+ setPressBookmark(bookmarkedPostIdList.includes(id));
+ } catch (error) {
+ console.error(
+ "북마크 상태 조회 실패:",
+ error.response ? error.response.data : error.message,
+ );
+ }
+ };
+
+ useEffect(() => {
+ likedPosts();
+ bookmarkedPosts();
+ }, [id]);
+
return (
@@ -248,15 +322,18 @@ const PostPage = ({ route }) => {
{heart}
-
-
+
+
{bookmark}
-
+
번역하기
diff --git a/src/pages/member/BookmarkPostPage.jsx b/src/pages/member/BookmarkPostPage.jsx
index a86acf91..6ae75786 100644
--- a/src/pages/member/BookmarkPostPage.jsx
+++ b/src/pages/member/BookmarkPostPage.jsx
@@ -14,6 +14,7 @@ const BookmarkPostPage = () => {
try {
const bookmarkPostResponse = await getBookmarkPost();
setBookmarkPostList(bookmarkPostResponse.data);
+ console.log(bookmarkPostResponse.data);
} catch (error) {
console.error(
"북마크한 게시글 조회 오류:",
@@ -28,7 +29,10 @@ const BookmarkPostPage = () => {
-
+