From 3e576120544e86ba25bce0c62fbbacdc6b5aa555 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 19:07:51 +0900 Subject: [PATCH 01/20] :art: tag auto-complete finished --- .../src/components/PostWriteTemplate/index.jsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx b/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx index 724b790f..26230900 100644 --- a/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx +++ b/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx @@ -44,7 +44,6 @@ export const PostWriteTemplate = ({ initial, mode }) => { const darkMode = useContext(DarkModeContext); const posts = useContext(PostsDataContext); - // const updateTempTag = (e) => setPost({ ...post, temp_tag: e.target.value }); const updateTags = () => { const data = { ...post }; const validTags = data.tags.filter((tag) => !!tag); @@ -52,10 +51,10 @@ export const PostWriteTemplate = ({ initial, mode }) => { data.tags.push({ id: tagSorted.length === 0 ? 1 : tagSorted[tagSorted.length - 1].id + 1, - content: post.temp_tag, + content: tagInputValue, }); - data.temp_tag = ""; setPost(data); + setTagInputValue(""); }; const updateTitle = (e) => setPost({ ...post, title: e.target.value }); const updateContent = (e) => setPost({ ...post, content: e.target.value }); @@ -63,13 +62,8 @@ export const PostWriteTemplate = ({ initial, mode }) => { const data = { ...post }; const afterDeleted = data.tags.filter((tag) => tag && tag.id !== tagId); setPost({ ...post, tags: afterDeleted }); - // data.tags.forEach((tag, index, array) => { - // if (tag && tag.id === tagId) array[index] = null; - // }); }; - // tag autoComplete - const onSumbitMethod = (mode) => { if (mode === "작성") { alert("게시물을 등록합니다."); @@ -159,13 +153,14 @@ export const PostWriteTemplate = ({ initial, mode }) => { 추가 -
+
{autoCompletes && autoCompletes.map((autoComplete) => ( From 71339c8df9504c826eca50538cb82af31e801be9 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 19:09:42 +0900 Subject: [PATCH 02/20] :sprakled: added comment dummy data --- .../components/PostWriteTemplate/index.jsx | 1 + lionblog-taehyeong/src/data/comment.js | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 lionblog-taehyeong/src/data/comment.js diff --git a/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx b/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx index 26230900..ac5a3889 100644 --- a/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx +++ b/lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx @@ -56,6 +56,7 @@ export const PostWriteTemplate = ({ initial, mode }) => { setPost(data); setTagInputValue(""); }; + const updateTitle = (e) => setPost({ ...post, title: e.target.value }); const updateContent = (e) => setPost({ ...post, content: e.target.value }); const deleteTag = (tagId) => { diff --git a/lionblog-taehyeong/src/data/comment.js b/lionblog-taehyeong/src/data/comment.js new file mode 100644 index 00000000..f95a23e4 --- /dev/null +++ b/lionblog-taehyeong/src/data/comment.js @@ -0,0 +1,35 @@ +// dummy data +const comments = [ + { + id: 1, + content: "새해 복 많이 받으세요^^", + created_at: "2024-01-01T15:09:43Z", + post: 1, + author: { + id: 2, + username: "user2", + }, + }, + { + id: 2, + content: "축구 2대 0;;;", + created_at: "2024-02-07T15:09:43Z", + post: 1, + author: { + id: 3, + username: "user3", + }, + }, + { + id: 3, + content: "망할 개강이야...", + created_at: "2024-03-02T15:09:43Z", + post: 1, + author: { + id: 4, + username: "user4", + }, + }, +]; + +export default comments; From 21d874cac0c8dee16420649f24158fdee0e8dcba Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 19:13:18 +0900 Subject: [PATCH 03/20] :sparkles: added comment template --- .../src/components/Comment/CommentElement.jsx | 42 +++++++++++++++++++ .../src/components/Comment/index.jsx | 29 +++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 lionblog-taehyeong/src/components/Comment/CommentElement.jsx create mode 100644 lionblog-taehyeong/src/components/Comment/index.jsx diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx new file mode 100644 index 00000000..1c7c72ea --- /dev/null +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -0,0 +1,42 @@ +import { useState, useEffect } from "react"; + +const CommentElement = (props) => { + /* TODO: props 받기 + Hint: src/components/Comment/index.jsx에서 어떠한 props를 넘겨주는지 확인해보세요! */ + + /* TODO: 댓글을 수정하는 input의 value를 관리하기 위한 state 작성 + Hint: 댓글의 내용을 저장하는 state와 수정 중인지 여부를 저장하는 state를 따로 만드는 게 좋겠죠? */ + + // comment created_at 전처리 + const date = new Date(comment.created_at); + const year = date.getFullYear(); + let month = date.getMonth() + 1; + month = month < 10 ? `0${month}` : month; + let day = date.getDate(); + day = day < 10 ? `0${day}` : day; + + const handleEditComment = () => { + alert("댓글 수정"); // add api call for editing comment + }; + + useEffect(() => { + // add api call to check if user is the author of the comment + }, []); + + return ( +
+
+ {/* {수정 중 ? :

댓글 내용

} */} + + + {year}.{month}.{day} + +
+ +
+ {/* {수정 중 ? 취소, 완료 버튼 : 수정, 삭제 버튼} */} +
+
+ ); +}; +export default CommentElement; diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx new file mode 100644 index 00000000..362bc4e6 --- /dev/null +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -0,0 +1,29 @@ +import { useState } from "react"; +import comments from "../../data/comments"; // dummy data +import CommentElement from "./CommentElement"; + +const Comment = ({ postId }) => { + // TODO: comments를 저장하기 위한 state를 만들어주세요 + // TODO: 새로운 댓글을 추가하기 위한 state를 만들어주세요 + + const handleCommentSubmit = (e) => { + e.preventDefault(); + alert("댓글 작성"); // add api call for creating comment + // TODO: 댓글을 추가했으니 새로운 댓글을 저장하는 state를 초기화해야겠죠? + }; + + const handleCommentDelete = (commentId) => { + console.log(commentId); + alert("댓글 삭제"); // add api call for deleting comment + }; + + return ( +
+

Comments

+ +
+
+ ); +}; + +export default Comment; From fd319f17ff40b4fc15be6b0be4801c177952ad90 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 20:01:43 +0900 Subject: [PATCH 04/20] :sparkles: completed comment submit --- .../src/components/Comment/CommentElement.jsx | 43 ++++++++++-- .../src/components/Comment/index.jsx | 66 ++++++++++++++++--- lionblog-taehyeong/src/index.css | 2 +- .../src/routes/PostDetailPage.jsx | 2 + 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index 1c7c72ea..b20b4e63 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -1,8 +1,7 @@ import { useState, useEffect } from "react"; -const CommentElement = (props) => { - /* TODO: props 받기 - Hint: src/components/Comment/index.jsx에서 어떠한 props를 넘겨주는지 확인해보세요! */ +const CommentElement = ({ comment, handleCommentDelete }) => { + const [isEditMode, setIsEditMode] = useState(false); /* TODO: 댓글을 수정하는 input의 value를 관리하기 위한 state 작성 Hint: 댓글의 내용을 저장하는 state와 수정 중인지 여부를 저장하는 state를 따로 만드는 게 좋겠죠? */ @@ -19,6 +18,16 @@ const CommentElement = (props) => { alert("댓글 수정"); // add api call for editing comment }; + const toEditMode = (e) => { + e.preventDefault(); + setIsEditMode(true); + }; + + const toShowMode = (e) => { + e.preventDefault(); + setIsEditMode(false); + }; + useEffect(() => { // add api call to check if user is the author of the comment }, []); @@ -26,7 +35,11 @@ const CommentElement = (props) => { return (
- {/* {수정 중 ? :

댓글 내용

} */} + {isEditMode ? ( + + ) : ( +

{comment.content}

+ )} {year}.{month}.{day} @@ -34,7 +47,27 @@ const CommentElement = (props) => {
- {/* {수정 중 ? 취소, 완료 버튼 : 수정, 삭제 버튼} */} + {isEditMode ? ( + <> + + + + ) : ( + <> + + + + )}
); diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 362bc4e6..4f689419 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -1,27 +1,77 @@ -import { useState } from "react"; -import comments from "../../data/comments"; // dummy data +import { useState, useEffect } from "react"; +import comments from "../../data/comment"; // dummy data import CommentElement from "./CommentElement"; const Comment = ({ postId }) => { - // TODO: comments를 저장하기 위한 state를 만들어주세요 + const [commentsData, setCommentsData] = useState([]); + const [commentInputValue, setCommentInputValue] = useState(""); // TODO: 새로운 댓글을 추가하기 위한 state를 만들어주세요 + const handleCommentInputChange = (e) => { + const { value } = e.target; + setCommentInputValue(value); + }; + const handleCommentSubmit = (e) => { e.preventDefault(); + if (commentInputValue.length === 0) return; + + const sortedData = commentsData.sort((a, b) => a.id - b.id); + const newId = sortedData[sortedData.length - 1].id + 1; + setCommentsData([ + ...commentsData, + { + id: newId, + content: commentInputValue, + created_at: "2024-01-01T15:09:43Z", + post: 1, + author: { + id: 2, + username: "user2", + }, + }, + ]); alert("댓글 작성"); // add api call for creating comment - // TODO: 댓글을 추가했으니 새로운 댓글을 저장하는 state를 초기화해야겠죠? + + setCommentInputValue(""); }; - const handleCommentDelete = (commentId) => { - console.log(commentId); + const handleCommentDelete = (commentId) => (e) => { + e.preventDefault(); + const updatedComments = commentsData.filter( + (comment) => comment.id !== commentId + ); + setCommentsData([...updatedComments]); alert("댓글 삭제"); // add api call for deleting comment }; + useEffect(() => { + setCommentsData(comments); + }, []); + return (

Comments

- -
+ {commentsData && + commentsData.map((comment) => ( + + ))} +
+ + +
); }; diff --git a/lionblog-taehyeong/src/index.css b/lionblog-taehyeong/src/index.css index ffc56dce..42a2c0da 100644 --- a/lionblog-taehyeong/src/index.css +++ b/lionblog-taehyeong/src/index.css @@ -29,7 +29,7 @@ } /* 모든 input 일괄 적용 */ .input { - @apply border-2 w-full px-6 py-3 rounded-2xl bg-transparent placeholder-opacity-50 focus:outline-none focus:ring-2 focus:ring-orange-400 focus:border-transparent; + @apply border-2 grow px-6 py-3 rounded-2xl bg-transparent placeholder-opacity-50 focus:outline-none focus:ring-2 focus:ring-orange-400 focus:border-transparent; } .input-dark { diff --git a/lionblog-taehyeong/src/routes/PostDetailPage.jsx b/lionblog-taehyeong/src/routes/PostDetailPage.jsx index 6c773056..13752c11 100644 --- a/lionblog-taehyeong/src/routes/PostDetailPage.jsx +++ b/lionblog-taehyeong/src/routes/PostDetailPage.jsx @@ -3,6 +3,7 @@ import { BigPost } from "../components/Posts"; import { useEffect, useState, useContext } from "react"; import { useParams, Link, useNavigate } from "react-router-dom"; import { PostsDataContext } from "../App"; +import Comment from "../components/Comment"; const PostDetailPage = () => { const navigate = useNavigate(); @@ -45,6 +46,7 @@ const PostDetailPage = () => { {post && ( <> +
From 1d8023a28812d1b88cac2473cf835c4f037d2a0f Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 20:11:54 +0900 Subject: [PATCH 05/20] :art: added custom style to comment edit button --- lionblog-taehyeong/src/App.js | 2 +- .../src/components/Comment/CommentElement.jsx | 8 ++++---- lionblog-taehyeong/src/components/Comment/index.jsx | 2 +- lionblog-taehyeong/src/index.css | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lionblog-taehyeong/src/App.js b/lionblog-taehyeong/src/App.js index 59c5f9c9..87f2c086 100644 --- a/lionblog-taehyeong/src/App.js +++ b/lionblog-taehyeong/src/App.js @@ -16,7 +16,7 @@ export const DarkModeContext = createContext(false); export const PostsDataContext = createContext(null); function App() { - const [darkMode, setDarkMode] = useState(false); + const [darkMode, setDarkMode] = useState(true); const darkModeToggle = () => setDarkMode(!darkMode); diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index b20b4e63..5c5870e5 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -49,21 +49,21 @@ const CommentElement = ({ comment, handleCommentDelete }) => {
{isEditMode ? ( <> - - + ) : ( <> - diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 4f689419..87372146 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -50,7 +50,7 @@ const Comment = ({ postId }) => { }, []); return ( -
+

Comments

{commentsData && commentsData.map((comment) => ( diff --git a/lionblog-taehyeong/src/index.css b/lionblog-taehyeong/src/index.css index 42a2c0da..ace0d206 100644 --- a/lionblog-taehyeong/src/index.css +++ b/lionblog-taehyeong/src/index.css @@ -20,6 +20,11 @@ .button { @apply bg-orange-400 text-white font-medium hover:text-black rounded-2xl text-lg px-7 py-2; } + +.button-no-bg { + @apply font-medium px-3 py-3 hover:opacity-50; +} + /* 모든 form 일괄 적용 */ .form { @apply w-full flex flex-col items-center; From 45b59547e81d80216365e0937c7ef83bb0db6ae8 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 20:17:39 +0900 Subject: [PATCH 06/20] :art: finished comment edit --- .../src/components/Comment/CommentElement.jsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index 5c5870e5..363a9e6d 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -2,6 +2,7 @@ import { useState, useEffect } from "react"; const CommentElement = ({ comment, handleCommentDelete }) => { const [isEditMode, setIsEditMode] = useState(false); + const [content, setContent] = useState(comment.content); /* TODO: 댓글을 수정하는 input의 value를 관리하기 위한 state 작성 Hint: 댓글의 내용을 저장하는 state와 수정 중인지 여부를 저장하는 state를 따로 만드는 게 좋겠죠? */ @@ -14,8 +15,9 @@ const CommentElement = ({ comment, handleCommentDelete }) => { let day = date.getDate(); day = day < 10 ? `0${day}` : day; - const handleEditComment = () => { - alert("댓글 수정"); // add api call for editing comment + const handleEditComment = (e) => { + e.preventDefault(); + setIsEditMode(false); }; const toEditMode = (e) => { @@ -36,9 +38,13 @@ const CommentElement = ({ comment, handleCommentDelete }) => {
{isEditMode ? ( - + setContent(e.target.value)} + /> ) : ( -

{comment.content}

+

{content}

)} @@ -52,7 +58,9 @@ const CommentElement = ({ comment, handleCommentDelete }) => { - + ) : ( <> From 4d57667de046a2ab4fab8a4553b8685c55607eb4 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 20:23:06 +0900 Subject: [PATCH 07/20] :zap: separated new input value from data in comment edit page --- lionblog-taehyeong/src/components/Comment/CommentElement.jsx | 5 ++++- lionblog-taehyeong/src/components/Comment/index.jsx | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index 363a9e6d..acfc3190 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; const CommentElement = ({ comment, handleCommentDelete }) => { const [isEditMode, setIsEditMode] = useState(false); const [content, setContent] = useState(comment.content); + const [editInputValue, setEditInputValue] = useState(""); /* TODO: 댓글을 수정하는 input의 value를 관리하기 위한 state 작성 Hint: 댓글의 내용을 저장하는 state와 수정 중인지 여부를 저장하는 state를 따로 만드는 게 좋겠죠? */ @@ -17,7 +18,9 @@ const CommentElement = ({ comment, handleCommentDelete }) => { const handleEditComment = (e) => { e.preventDefault(); + setContent(editInputValue); setIsEditMode(false); + setEditInputValue(""); }; const toEditMode = (e) => { @@ -41,7 +44,7 @@ const CommentElement = ({ comment, handleCommentDelete }) => { setContent(e.target.value)} + onChange={(e) => setEditInputValue(e.target.value)} /> ) : (

{content}

diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 87372146..fd192ffc 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -5,7 +5,6 @@ import CommentElement from "./CommentElement"; const Comment = ({ postId }) => { const [commentsData, setCommentsData] = useState([]); const [commentInputValue, setCommentInputValue] = useState(""); - // TODO: 새로운 댓글을 추가하기 위한 state를 만들어주세요 const handleCommentInputChange = (e) => { const { value } = e.target; From 08eeca0baff86070ea2bf07a5098c889895948de Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 20:29:38 +0900 Subject: [PATCH 08/20] :sparkles: finished week5-hw --- lionblog-taehyeong/src/components/Comment/index.jsx | 2 -- lionblog-taehyeong/src/routes/PostDetailPage.jsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index fd192ffc..624dff21 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -30,7 +30,6 @@ const Comment = ({ postId }) => { }, }, ]); - alert("댓글 작성"); // add api call for creating comment setCommentInputValue(""); }; @@ -41,7 +40,6 @@ const Comment = ({ postId }) => { (comment) => comment.id !== commentId ); setCommentsData([...updatedComments]); - alert("댓글 삭제"); // add api call for deleting comment }; useEffect(() => { diff --git a/lionblog-taehyeong/src/routes/PostDetailPage.jsx b/lionblog-taehyeong/src/routes/PostDetailPage.jsx index 13752c11..74287d69 100644 --- a/lionblog-taehyeong/src/routes/PostDetailPage.jsx +++ b/lionblog-taehyeong/src/routes/PostDetailPage.jsx @@ -46,7 +46,7 @@ const PostDetailPage = () => { {post && ( <> - +
From fb7ea3ad68e70129218ddf75f07bf7137cd3a0e3 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 21:07:49 +0900 Subject: [PATCH 09/20] :art: added selecting multiple tags in serach --- lionblog-taehyeong/src/routes/HomePage.jsx | 43 ++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/lionblog-taehyeong/src/routes/HomePage.jsx b/lionblog-taehyeong/src/routes/HomePage.jsx index eeff4a38..c843e77c 100644 --- a/lionblog-taehyeong/src/routes/HomePage.jsx +++ b/lionblog-taehyeong/src/routes/HomePage.jsx @@ -7,29 +7,21 @@ import { PostsDataContext } from "../App"; const HomePage = () => { // const postList = posts; const postList = useContext(PostsDataContext); - - // const [postList, setPostList] = useState(posts); + const [visiblePosts, setVisiblePosts] = useState(postList); const [tags, setTags] = useState([]); const [searchTags, setSearchTags] = useState([]); - const [searchValue, setSearchValue] = useState(""); + const [searchValue, setSearchValue] = useState([]); const handleChange = (e) => {}; - // const handleTagFilter = (e) => { - // const { innerText } = e.target; - // if (searchValue === innerText.substring(1)) { - // setSearchValue(""); - // setPostList(posts); - // } else { - // const activeTag = innerText.substring(1); - // setSearchValue(activeTag); - // const newPosts = posts.filter((post) => - // post.tags.find((tag) => tag.content === activeTag) - // ); - // setPostList(newPosts); - // } - // }; + const handleTagFilter = (e) => { + const { innerText } = e.target; + const tag = innerText.substring(1); + searchValue.includes(tag) + ? setSearchValue([...searchValue.filter((v) => v !== tag)]) + : setSearchValue([...searchValue, tag]); + }; useEffect(() => { const tagList = postList.reduce((acc, post) => { @@ -40,6 +32,16 @@ const HomePage = () => { setSearchTags([...tagList]); }, []); + useEffect(() => { + if (searchValue.length === 0) setVisiblePosts(postList); + else { + const newPosts = postList.filter((post) => + searchValue.every((v) => post.tags.find((t) => t.content === v)) + ); + setVisiblePosts(newPosts); + } + }, [searchValue]); + return (
@@ -58,7 +60,10 @@ const HomePage = () => { return ( @@ -66,7 +71,7 @@ const HomePage = () => { })}
- {postList.map((post) => + {visiblePosts.map((post) => post ? : null )}
From d786c58b45b84e15c098b3fe71b42dee3f542fe1 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Mon, 8 Apr 2024 21:13:44 +0900 Subject: [PATCH 10/20] added the new comment data with time now --- lionblog-taehyeong/src/components/Comment/index.jsx | 2 +- lionblog-taehyeong/src/routes/HomePage.jsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 624dff21..d56c3ae5 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -22,7 +22,7 @@ const Comment = ({ postId }) => { { id: newId, content: commentInputValue, - created_at: "2024-01-01T15:09:43Z", + created_at: new Date(), post: 1, author: { id: 2, diff --git a/lionblog-taehyeong/src/routes/HomePage.jsx b/lionblog-taehyeong/src/routes/HomePage.jsx index c843e77c..713dadce 100644 --- a/lionblog-taehyeong/src/routes/HomePage.jsx +++ b/lionblog-taehyeong/src/routes/HomePage.jsx @@ -13,7 +13,11 @@ const HomePage = () => { const [searchTags, setSearchTags] = useState([]); const [searchValue, setSearchValue] = useState([]); - const handleChange = (e) => {}; + const handleChange = (e) => { + const { value } = e.target; + const newTags = tags.filter((tag) => tag.includes(value)); + setSearchTags(newTags); + }; const handleTagFilter = (e) => { const { innerText } = e.target; From 40d622ce518bbc15182980099407bcd86e6fa4ed Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 18:43:28 +0900 Subject: [PATCH 11/20] :bug: fixed the input of the post-create-page to full-width --- .../src/components/Header/index.jsx | 32 +++++++++++++++---- .../components/PostWriteTemplate/index.jsx | 4 +-- lionblog-taehyeong/src/index.css | 4 +-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lionblog-taehyeong/src/components/Header/index.jsx b/lionblog-taehyeong/src/components/Header/index.jsx index b43c4fb7..ee1b45a0 100644 --- a/lionblog-taehyeong/src/components/Header/index.jsx +++ b/lionblog-taehyeong/src/components/Header/index.jsx @@ -1,5 +1,5 @@ import { Link } from "react-router-dom"; -import { useContext } from "react"; +import { useContext, useState, useEffect } from "react"; import { DarkModeContext } from "../../App"; import lion from "../../assets/images/lion.jpeg"; @@ -7,6 +7,16 @@ import lion from "../../assets/images/lion.jpeg"; const Header = ({ darkModeToggle }) => { const darkMode = useContext(DarkModeContext); + const [isUserLoggedIn, setIsUserLoggedIn] = useState(false); // 로그인 여부 상태, 우선 false로 초기화 + + const handleSignOut = () => { + // TODO: 이후 api 연결 시 token 제거 + }; + + useEffect(() => { + // TODO: 이후 api 연결 시 유효한 token이 있다면 setIsUserLoggedIn(true)로 상태 변경하는 코드 작성 + }, []); + return (
{
SNULION BLOG
- - sign in - - - sign up - + {isUserLoggedIn ? ( + + sign out + + ) : ( + <> + + sign in + + + sign up + + + )}
-
+
{searchTags.map((tag) => { return (
-
+
{visiblePosts.map((post) => post ? : null )} From 339b555db880a3ba035b6689603787e3f1e833e5 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 19:23:01 +0900 Subject: [PATCH 15/20] :sparkles: added custom media query hook and implemented it to the header --- .../src/components/Header/index.jsx | 56 ++++++++++--------- .../src/hooks/useMediaQuery.jsx | 24 ++++++++ 2 files changed, 54 insertions(+), 26 deletions(-) create mode 100644 lionblog-taehyeong/src/hooks/useMediaQuery.jsx diff --git a/lionblog-taehyeong/src/components/Header/index.jsx b/lionblog-taehyeong/src/components/Header/index.jsx index ee1b45a0..caecd93b 100644 --- a/lionblog-taehyeong/src/components/Header/index.jsx +++ b/lionblog-taehyeong/src/components/Header/index.jsx @@ -1,11 +1,13 @@ import { Link } from "react-router-dom"; import { useContext, useState, useEffect } from "react"; import { DarkModeContext } from "../../App"; +import { useMediaQuery } from "../../hooks/useMediaQuery"; import lion from "../../assets/images/lion.jpeg"; const Header = ({ darkModeToggle }) => { const darkMode = useContext(DarkModeContext); + const isMobile = useMediaQuery("(max-width: 640px)"); const [isUserLoggedIn, setIsUserLoggedIn] = useState(false); // 로그인 여부 상태, 우선 false로 초기화 @@ -25,33 +27,35 @@ const Header = ({ darkModeToggle }) => { lion
SNULION BLOG
-
- {isUserLoggedIn ? ( - - sign out - - ) : ( - <> - - sign in + {isMobile ? null : ( +
+ {isUserLoggedIn ? ( + + sign out - - sign up - - - )} - -
+ ) : ( + <> + + sign in + + + sign up + + + )} + +
+ )}
); }; diff --git a/lionblog-taehyeong/src/hooks/useMediaQuery.jsx b/lionblog-taehyeong/src/hooks/useMediaQuery.jsx new file mode 100644 index 00000000..91faf71b --- /dev/null +++ b/lionblog-taehyeong/src/hooks/useMediaQuery.jsx @@ -0,0 +1,24 @@ +import { useState, useEffect, useCallback } from "react"; + +const getQueryMatches = (query) => { + if (typeof window !== "undefined") return window.matchMedia(query).matches; + return false; +}; + +export const useMediaQuery = (query) => { + const [matches, setMatches] = useState(getQueryMatches(query)); + + const handleChange = useCallback(() => { + setMatches(getQueryMatches(query)); + }, []); + + useEffect(() => { + const matchMedia = window.matchMedia(query); + + matchMedia.addEventListener("change", handleChange); + + return () => matchMedia.removeEventListener("change", handleChange); + }, [query]); + + return matches; +}; From 7e05854a7a5b3bca50dedc768d83a07a09bcc230 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 19:42:45 +0900 Subject: [PATCH 16/20] :art: implemented Intl.DateTimeFormat for the comment created_at --- .../src/components/Comment/CommentElement.jsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index acfc3190..72a9f798 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -5,16 +5,16 @@ const CommentElement = ({ comment, handleCommentDelete }) => { const [content, setContent] = useState(comment.content); const [editInputValue, setEditInputValue] = useState(""); - /* TODO: 댓글을 수정하는 input의 value를 관리하기 위한 state 작성 - Hint: 댓글의 내용을 저장하는 state와 수정 중인지 여부를 저장하는 state를 따로 만드는 게 좋겠죠? */ - // comment created_at 전처리 - const date = new Date(comment.created_at); - const year = date.getFullYear(); - let month = date.getMonth() + 1; - month = month < 10 ? `0${month}` : month; - let day = date.getDate(); - day = day < 10 ? `0${day}` : day; + const date = new Intl.DateTimeFormat("en-CA", { + formatString: "yyyy.mm.dd", + + year: "numeric", + month: "2-digit", + day: "2-digit", + }) + .format(new Date(comment.created_at)) + .replaceAll("-", "."); const handleEditComment = (e) => { e.preventDefault(); @@ -51,7 +51,8 @@ const CommentElement = ({ comment, handleCommentDelete }) => { )} - {year}.{month}.{day} + {/* {year}.{month}.{day} */} + {date}
From 7aa88afeddbd7e28fdac9905ce5e4bb954bc1ffb Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 19:52:17 +0900 Subject: [PATCH 17/20] :bug: added proper key to individual comment component --- lionblog-taehyeong/src/components/Comment/CommentElement.jsx | 5 +---- lionblog-taehyeong/src/components/Comment/index.jsx | 4 +++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx index 72a9f798..cb651fb4 100644 --- a/lionblog-taehyeong/src/components/Comment/CommentElement.jsx +++ b/lionblog-taehyeong/src/components/Comment/CommentElement.jsx @@ -50,10 +50,7 @@ const CommentElement = ({ comment, handleCommentDelete }) => {

{content}

)} - - {/* {year}.{month}.{day} */} - {date} - + {date}
diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index d56c3ae5..7ee3bf60 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -17,6 +17,7 @@ const Comment = ({ postId }) => { const sortedData = commentsData.sort((a, b) => a.id - b.id); const newId = sortedData[sortedData.length - 1].id + 1; + console.log(newId); setCommentsData([ ...commentsData, { @@ -40,6 +41,7 @@ const Comment = ({ postId }) => { (comment) => comment.id !== commentId ); setCommentsData([...updatedComments]); + console.log(commentId); }; useEffect(() => { @@ -52,7 +54,7 @@ const Comment = ({ postId }) => { {commentsData && commentsData.map((comment) => ( From b22d367a842a6b14a5306f8faf76cb5c79aea3bd Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 20:27:27 +0900 Subject: [PATCH 18/20] modified responsive target range in the small post --- lionblog-taehyeong/src/routes/HomePage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lionblog-taehyeong/src/routes/HomePage.jsx b/lionblog-taehyeong/src/routes/HomePage.jsx index 4ed65132..51a9d2d9 100644 --- a/lionblog-taehyeong/src/routes/HomePage.jsx +++ b/lionblog-taehyeong/src/routes/HomePage.jsx @@ -74,7 +74,7 @@ const HomePage = () => { ); })}
-
+
{visiblePosts.map((post) => post ? : null )} From 828bb88c610264661c94fc3715aa078a5648f4f8 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 20:33:00 +0900 Subject: [PATCH 19/20] implemented join between comment and post id --- lionblog-taehyeong/src/components/Comment/index.jsx | 8 +++++--- lionblog-taehyeong/src/routes/PostDetailPage.jsx | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 7ee3bf60..59258de9 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -17,7 +17,7 @@ const Comment = ({ postId }) => { const sortedData = commentsData.sort((a, b) => a.id - b.id); const newId = sortedData[sortedData.length - 1].id + 1; - console.log(newId); + setCommentsData([ ...commentsData, { @@ -45,8 +45,10 @@ const Comment = ({ postId }) => { }; useEffect(() => { - setCommentsData(comments); - }, []); + setCommentsData( + comments.filter((comment) => comment.post === parseInt(postId)) + ); + }, [postId]); return (
diff --git a/lionblog-taehyeong/src/routes/PostDetailPage.jsx b/lionblog-taehyeong/src/routes/PostDetailPage.jsx index 74287d69..1779553f 100644 --- a/lionblog-taehyeong/src/routes/PostDetailPage.jsx +++ b/lionblog-taehyeong/src/routes/PostDetailPage.jsx @@ -27,6 +27,7 @@ const PostDetailPage = () => { useEffect(() => { const post = posts.find((post) => post && post.id === parseInt(postId)); if (post) setPost(post); + // console.log(postId); }, [postId]); useEffect(() => { @@ -46,7 +47,7 @@ const PostDetailPage = () => { {post && ( <> - +
From 39360a22006cad79eff4252bfa094ca4f07425e6 Mon Sep 17 00:00:00 2001 From: Taehyeungkim Date: Thu, 11 Apr 2024 20:41:34 +0900 Subject: [PATCH 20/20] :bug: fixed the error having been occured when adding first comment to the post --- lionblog-taehyeong/src/components/Comment/index.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lionblog-taehyeong/src/components/Comment/index.jsx b/lionblog-taehyeong/src/components/Comment/index.jsx index 59258de9..57ba3662 100644 --- a/lionblog-taehyeong/src/components/Comment/index.jsx +++ b/lionblog-taehyeong/src/components/Comment/index.jsx @@ -15,8 +15,11 @@ const Comment = ({ postId }) => { e.preventDefault(); if (commentInputValue.length === 0) return; - const sortedData = commentsData.sort((a, b) => a.id - b.id); - const newId = sortedData[sortedData.length - 1].id + 1; + const newId = + commentsData.length > 0 + ? commentsData.sort((a, b) => a.id - b.id)[commentsData.length - 1].id + + 1 + : 1; setCommentsData([ ...commentsData,