From b53e6886d23193ccfd4ac158cdf9151624ff5795 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 11 Jan 2024 10:47:09 +0900 Subject: [PATCH 1/6] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Mypage/DeleteMemberButton.tsx | 30 ++++++++++++++++++++ src/components/common/BackBox/BackBox.tsx | 4 ++- src/pages/mypage/editUserInfo.page.tsx | 15 +++++++++- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/components/Mypage/DeleteMemberButton.tsx diff --git a/src/components/Mypage/DeleteMemberButton.tsx b/src/components/Mypage/DeleteMemberButton.tsx new file mode 100644 index 00000000..fb359241 --- /dev/null +++ b/src/components/Mypage/DeleteMemberButton.tsx @@ -0,0 +1,30 @@ +import { deleteMember } from '@api/member'; +import { UserInfoState } from '@recoil/Auth.atom'; +import { useNavigate } from 'react-router-dom'; +import { useSetRecoilState } from 'recoil'; + +const DeleteMemberButton = () => { + const setUserInfo = useSetRecoilState(UserInfoState); + const navigate = useNavigate(); + const onDeleteClick = async () => { + if (confirm('정말 탈퇴 하시겠습니까?')) { + try { + const res = await deleteMember(); + if (res.data.status === 200) { + setUserInfo(null); + navigate('/'); + alert('회원 탈퇴되었습니다. 감사합니다.'); + } + } catch (err) { + console.log(err); + } + } + }; + return ( + + ); +}; + +export default DeleteMemberButton; diff --git a/src/components/common/BackBox/BackBox.tsx b/src/components/common/BackBox/BackBox.tsx index 66c7dae4..d440deb9 100644 --- a/src/components/common/BackBox/BackBox.tsx +++ b/src/components/common/BackBox/BackBox.tsx @@ -9,6 +9,7 @@ interface Props { showSkip?: boolean; skipHandler?: VoidFunction; showSave?: boolean; + saveHandler?: VoidFunction; } const BackBox = ({ @@ -18,6 +19,7 @@ const BackBox = ({ showSkip, skipHandler, showSave, + saveHandler, }: Props) => { const navigate = useNavigate(); @@ -28,7 +30,7 @@ const BackBox = ({ skipHandler && skipHandler(); }; const onSaveClick = () => { - console.log('저장 버튼 클릭'); + saveHandler && saveHandler(); }; return ( diff --git a/src/pages/mypage/editUserInfo.page.tsx b/src/pages/mypage/editUserInfo.page.tsx index 76e3a43f..13fe9072 100644 --- a/src/pages/mypage/editUserInfo.page.tsx +++ b/src/pages/mypage/editUserInfo.page.tsx @@ -1,5 +1,18 @@ +import DeleteMemberButton from '@components/Mypage/DeleteMemberButton'; +import { BackBox } from '@components/common'; + const EditUserInfo = () => { - return <>회원 정보 수정 페이지; + return ( + <> + {}}> + 회원정보 수정 + +
+ + +
+ + ); }; export default EditUserInfo; From 5fcbd614a747313791916b6ed3f11614f2c8ffca Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 11 Jan 2024 10:49:26 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Design:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=EB=B2=84=ED=8A=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/mypage/editUserInfo.page.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/mypage/editUserInfo.page.tsx b/src/pages/mypage/editUserInfo.page.tsx index 13fe9072..79bf4dfe 100644 --- a/src/pages/mypage/editUserInfo.page.tsx +++ b/src/pages/mypage/editUserInfo.page.tsx @@ -1,5 +1,6 @@ import DeleteMemberButton from '@components/Mypage/DeleteMemberButton'; import { BackBox } from '@components/common'; +import { Link } from 'react-router-dom'; const EditUserInfo = () => { return ( @@ -7,8 +8,10 @@ const EditUserInfo = () => { {}}> 회원정보 수정 -
- +
+ + 비밀번호 변경 +
From b71c8dc014c9ce85ab4f920e93714c9ca83f9b71 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 11 Jan 2024 20:34:16 +0900 Subject: [PATCH 3/6] =?UTF-8?q?Fix:=20=EB=A6=AC=ED=94=84=EB=A0=88=EC=8B=9C?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=A0=80=EC=9E=A5=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/authClient.ts | 3 +++ src/api/client.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/authClient.ts b/src/api/authClient.ts index e4ce29c4..af0740bd 100644 --- a/src/api/authClient.ts +++ b/src/api/authClient.ts @@ -1,5 +1,6 @@ import { getItem, setItem } from '@utils/localStorageFun'; import axios from 'axios'; +import { postLogout } from './auth'; const authClient = axios.create({ baseURL: import.meta.env.VITE_SERVER_URL, @@ -45,7 +46,9 @@ authClient.interceptors.response.use( // 2. 리프레시 토큰이 만료된 경우(리프레시 토큰이 존재하지 않습니다.) // 3. 리프레시 토큰이 없는 경우 // 전부 비로그인으로 처리합니다. + // TODO 서지수 | 로그아웃 요청 console.log('401에러 발생 로그인 페이지로 이동시키면 됩니다.'); + postLogout(); } return Promise.reject(error); }, diff --git a/src/api/client.ts b/src/api/client.ts index 50ed6965..930438d1 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -5,7 +5,7 @@ const client = axios.create({ headers: { 'Content-Type': 'application/json', }, - withCredentials: false, + withCredentials: true, }); export default client; From 9023f4fa07ac72867f0d1844f43ad076446fb9b9 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 11 Jan 2024 20:58:29 +0900 Subject: [PATCH 4/6] =?UTF-8?q?Refactor:=20=EB=A1=9C=EC=BB=AC=EC=8A=A4?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=EC=A7=80=20=EC=82=AD=EC=A0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/authClient.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/authClient.ts b/src/api/authClient.ts index af0740bd..9590a509 100644 --- a/src/api/authClient.ts +++ b/src/api/authClient.ts @@ -1,4 +1,4 @@ -import { getItem, setItem } from '@utils/localStorageFun'; +import { getItem, removeItem, setItem } from '@utils/localStorageFun'; import axios from 'axios'; import { postLogout } from './auth'; @@ -49,6 +49,7 @@ authClient.interceptors.response.use( // TODO 서지수 | 로그아웃 요청 console.log('401에러 발생 로그인 페이지로 이동시키면 됩니다.'); postLogout(); + removeItem('accessToken'); } return Promise.reject(error); }, From 74151700f9c337485374226f03f27a1ac11d77cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Thu, 11 Jan 2024 23:54:28 +0900 Subject: [PATCH 5/6] =?UTF-8?q?Refactor:=20=EB=8C=93=EA=B8=80=20invalidate?= =?UTF-8?q?Queries=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailSectionTop/DetailTopButton.tsx | 19 +++++++++----- src/components/Review/ReviewComments.tsx | 2 +- src/components/common/nav/InputComment.tsx | 25 ++++++++++++++----- .../reviewComment/reviewComment.page.tsx | 1 + 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/components/DetailSectionTop/DetailTopButton.tsx b/src/components/DetailSectionTop/DetailTopButton.tsx index c1ffe145..107501b9 100644 --- a/src/components/DetailSectionTop/DetailTopButton.tsx +++ b/src/components/DetailSectionTop/DetailTopButton.tsx @@ -4,7 +4,8 @@ import { TopIcon } from '@components/common/icons/Icons'; export default function DetailTopButton() { const [showButton, setShowButton] = useState(true); - const scrollToTop = () => { + const scrollToTop = (e: React.MouseEvent) => { + e.stopPropagation(); window.scroll({ top: 0, behavior: 'smooth', @@ -27,14 +28,20 @@ export default function DetailTopButton() { }; }, []); + const shadowStyle = { + boxShadow: + '2px 2px 5px rgba(0, 0, 0, 0.4), -2px -2px 5px rgba(0, 0, 0, 0.1)', + }; + return ( showButton && (
-
- -
+ onClick={(e) => { + scrollToTop(e); + }} + className="sticky bottom-3 z-20 ml-auto flex h-12 w-12 items-center justify-center rounded-full bg-white " + style={shadowStyle}> +
) ); diff --git a/src/components/Review/ReviewComments.tsx b/src/components/Review/ReviewComments.tsx index a17dfdfd..65c5bef1 100644 --- a/src/components/Review/ReviewComments.tsx +++ b/src/components/Review/ReviewComments.tsx @@ -64,7 +64,7 @@ export default function ReviewComments() { {commentDataLength}
{commentDataLength == 0 && ( -
+
댓글이 없습니다.
첫 댓글을 작성해보세요!
diff --git a/src/components/common/nav/InputComment.tsx b/src/components/common/nav/InputComment.tsx index a6fdd8d3..abf1bfe8 100644 --- a/src/components/common/nav/InputComment.tsx +++ b/src/components/common/nav/InputComment.tsx @@ -10,14 +10,17 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; interface InputCommentProps { classNameName?: string; } + interface PostCommentMutationParams { comment: string; reviewId: number; } + interface EditCommentMutationParams { comment: string; targetCommentId: number; } + export const InputComment: React.FC = () => { const [comment, setComment] = useRecoilState(commentState); const params = useParams(); @@ -28,19 +31,29 @@ export const InputComment: React.FC = () => { const targetCommentId = useRecoilValue(targetCommentIdState); const queryClient = useQueryClient(); - const { mutate: postCommentMutate } = useMutation({ + const { mutate: postReviewMutate } = useMutation({ mutationFn: ({ comment, reviewId }: PostCommentMutationParams) => postComments(comment, reviewId), onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['reviewComments'] }); + queryClient.invalidateQueries({ + queryKey: ['reviewComments'], + }); + queryClient.invalidateQueries({ + queryKey: ['myReviews'], + }); }, onError: () => console.log('error'), }); - const { mutate: editCommentMutate } = useMutation({ + const { mutate: editReviewMutate } = useMutation({ mutationFn: ({ comment, targetCommentId }: EditCommentMutationParams) => putComments(comment, targetCommentId), onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['reviewComments'] }); + queryClient.invalidateQueries({ + queryKey: ['reviewComments'], + }); + queryClient.invalidateQueries({ + queryKey: ['myReviews'], + }); }, onError: () => console.log('error'), }); @@ -52,10 +65,10 @@ export const InputComment: React.FC = () => { const handleSubmit = async () => { if (isModifyingComment) { - await editCommentMutate({ comment, targetCommentId }); + await editReviewMutate({ comment, targetCommentId }); setIsModifyingComment(false); } else { - await postCommentMutate({ comment, reviewId }); + await postReviewMutate({ comment, reviewId }); } setComment(''); }; diff --git a/src/pages/reviewComment/reviewComment.page.tsx b/src/pages/reviewComment/reviewComment.page.tsx index 8e92ff28..3c17f3e9 100644 --- a/src/pages/reviewComment/reviewComment.page.tsx +++ b/src/pages/reviewComment/reviewComment.page.tsx @@ -1,5 +1,6 @@ import { DetailHeader } from '@components/common/header'; import { DetailReview, ReviewComments } from '@components/Review'; + const ReviewComment = () => { return ( <> From 48f36036484faffb5449aa46412ae44d837d9340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Fri, 12 Jan 2024 01:00:48 +0900 Subject: [PATCH 6/6] =?UTF-8?q?Fix:=20input=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailSectionTop/DetailTopButton.tsx | 19 ++--- src/components/Review/ReviewComments.tsx | 74 ++++++++++--------- src/components/common/nav/InputComment.tsx | 42 +++++------ src/pages/detail/detail.page.tsx | 4 +- 4 files changed, 66 insertions(+), 73 deletions(-) diff --git a/src/components/DetailSectionTop/DetailTopButton.tsx b/src/components/DetailSectionTop/DetailTopButton.tsx index 107501b9..c1ffe145 100644 --- a/src/components/DetailSectionTop/DetailTopButton.tsx +++ b/src/components/DetailSectionTop/DetailTopButton.tsx @@ -4,8 +4,7 @@ import { TopIcon } from '@components/common/icons/Icons'; export default function DetailTopButton() { const [showButton, setShowButton] = useState(true); - const scrollToTop = (e: React.MouseEvent) => { - e.stopPropagation(); + const scrollToTop = () => { window.scroll({ top: 0, behavior: 'smooth', @@ -28,20 +27,14 @@ export default function DetailTopButton() { }; }, []); - const shadowStyle = { - boxShadow: - '2px 2px 5px rgba(0, 0, 0, 0.4), -2px -2px 5px rgba(0, 0, 0, 0.1)', - }; - return ( showButton && (
{ - scrollToTop(e); - }} - className="sticky bottom-3 z-20 ml-auto flex h-12 w-12 items-center justify-center rounded-full bg-white " - style={shadowStyle}> - + onClick={scrollToTop} + className="scroll__container sticky bottom-3 z-20 flex cursor-pointer items-center justify-end"> +
+ +
) ); diff --git a/src/components/Review/ReviewComments.tsx b/src/components/Review/ReviewComments.tsx index 65c5bef1..fbdc53ae 100644 --- a/src/components/Review/ReviewComments.tsx +++ b/src/components/Review/ReviewComments.tsx @@ -63,43 +63,45 @@ export default function ReviewComments() { 댓글 {commentDataLength}
- {commentDataLength == 0 && ( -
-
댓글이 없습니다.
-
첫 댓글을 작성해보세요!
-
- )} - fetchNextPage()} - hasMore={hasNextPage} - loader={ -
- Loading ... +
+ {commentDataLength == 0 && ( +
+
댓글이 없습니다.
+
첫 댓글을 작성해보세요!
- }> -
- {reviewComments?.pages.map((group, index) => { - { - return ( - - {group?.data.data.comments.content.map((item: any) => ( - - ))} - - ); - } - })} -
- + )} + fetchNextPage()} + hasMore={hasNextPage} + loader={ +
+ Loading ... +
+ }> +
+ {reviewComments?.pages.map((group, index) => { + { + return ( + + {group?.data.data.comments.content.map((item: any) => ( + + ))} + + ); + } + })} +
+
+
{modalChildren === 'EditDelete' && } {modalChildren === 'MyAlert' && ( diff --git a/src/components/common/nav/InputComment.tsx b/src/components/common/nav/InputComment.tsx index abf1bfe8..76fbba1f 100644 --- a/src/components/common/nav/InputComment.tsx +++ b/src/components/common/nav/InputComment.tsx @@ -78,29 +78,27 @@ export const InputComment: React.FC = () => { } }; return ( - <> -
-
-
-
- -
-
- -
+
+
+
+
+ +
+
+
- +
); }; diff --git a/src/pages/detail/detail.page.tsx b/src/pages/detail/detail.page.tsx index cee1949a..99333eb4 100644 --- a/src/pages/detail/detail.page.tsx +++ b/src/pages/detail/detail.page.tsx @@ -1,7 +1,7 @@ import { DetailHeader } from '@components/common/header'; import DetailSectionTop from '@components/DetailSectionTop/DetailSectionTop'; import DetailSectionBottom from '@components/DetailSectionBottom/DetailSectionBottom'; -import { DetailTopButton } from '@components/DetailSectionTop'; +// import { DetailTopButton } from '@components/DetailSectionTop'; const DetailTours = () => { return ( @@ -9,7 +9,7 @@ const DetailTours = () => { - + {/* */} ); };