From a8ac1e5975cf01e46214db3c5485c9b3605d2762 Mon Sep 17 00:00:00 2001 From: Yoonkyoungme Date: Fri, 29 Dec 2023 09:39:27 +0900 Subject: [PATCH 01/63] =?UTF-8?q?init:=20=EC=95=84=EC=9D=B4=EC=BD=98=20svg?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/.gitkeep | 0 src/assets/icons/bookmark.svg | 9 +++++++++ src/assets/icons/chat.svg | 3 +++ src/assets/icons/comment.svg | 3 +++ src/assets/icons/commentDelete.svg | 3 +++ src/assets/icons/commentUpload.svg | 3 +++ src/assets/icons/edit.svg | 4 ++++ src/assets/icons/fileUpload.svg | 9 +++++++++ src/assets/icons/following.svg | 3 +++ src/assets/icons/notification.svg | 10 ++++++++++ src/assets/icons/prev_brown.svg | 3 +++ src/assets/icons/prev_white.svg | 3 +++ src/assets/icons/profile.svg | 3 +++ src/assets/icons/scrollTop.svg | 3 +++ src/assets/icons/search.svg | 3 +++ src/assets/icons/userlist.svg | 10 ++++++++++ src/assets/icons/write.svg | 4 ++++ 17 files changed, 76 insertions(+) delete mode 100644 src/assets/.gitkeep create mode 100644 src/assets/icons/bookmark.svg create mode 100644 src/assets/icons/chat.svg create mode 100644 src/assets/icons/comment.svg create mode 100644 src/assets/icons/commentDelete.svg create mode 100644 src/assets/icons/commentUpload.svg create mode 100644 src/assets/icons/edit.svg create mode 100644 src/assets/icons/fileUpload.svg create mode 100644 src/assets/icons/following.svg create mode 100644 src/assets/icons/notification.svg create mode 100644 src/assets/icons/prev_brown.svg create mode 100644 src/assets/icons/prev_white.svg create mode 100644 src/assets/icons/profile.svg create mode 100644 src/assets/icons/scrollTop.svg create mode 100644 src/assets/icons/search.svg create mode 100644 src/assets/icons/userlist.svg create mode 100644 src/assets/icons/write.svg diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/assets/icons/bookmark.svg b/src/assets/icons/bookmark.svg new file mode 100644 index 0000000..7b1d2d0 --- /dev/null +++ b/src/assets/icons/bookmark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icons/chat.svg b/src/assets/icons/chat.svg new file mode 100644 index 0000000..b0f3ef5 --- /dev/null +++ b/src/assets/icons/chat.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/comment.svg b/src/assets/icons/comment.svg new file mode 100644 index 0000000..1b9b5b4 --- /dev/null +++ b/src/assets/icons/comment.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/commentDelete.svg b/src/assets/icons/commentDelete.svg new file mode 100644 index 0000000..cf887b3 --- /dev/null +++ b/src/assets/icons/commentDelete.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/commentUpload.svg b/src/assets/icons/commentUpload.svg new file mode 100644 index 0000000..a0feb63 --- /dev/null +++ b/src/assets/icons/commentUpload.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/edit.svg b/src/assets/icons/edit.svg new file mode 100644 index 0000000..cb9f669 --- /dev/null +++ b/src/assets/icons/edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/fileUpload.svg b/src/assets/icons/fileUpload.svg new file mode 100644 index 0000000..d4c29a6 --- /dev/null +++ b/src/assets/icons/fileUpload.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icons/following.svg b/src/assets/icons/following.svg new file mode 100644 index 0000000..7e10723 --- /dev/null +++ b/src/assets/icons/following.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/notification.svg b/src/assets/icons/notification.svg new file mode 100644 index 0000000..3cf35be --- /dev/null +++ b/src/assets/icons/notification.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/prev_brown.svg b/src/assets/icons/prev_brown.svg new file mode 100644 index 0000000..6267db0 --- /dev/null +++ b/src/assets/icons/prev_brown.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/prev_white.svg b/src/assets/icons/prev_white.svg new file mode 100644 index 0000000..ad7d864 --- /dev/null +++ b/src/assets/icons/prev_white.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/profile.svg b/src/assets/icons/profile.svg new file mode 100644 index 0000000..d8838e9 --- /dev/null +++ b/src/assets/icons/profile.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/scrollTop.svg b/src/assets/icons/scrollTop.svg new file mode 100644 index 0000000..7e83ae9 --- /dev/null +++ b/src/assets/icons/scrollTop.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/search.svg b/src/assets/icons/search.svg new file mode 100644 index 0000000..9f55992 --- /dev/null +++ b/src/assets/icons/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/userlist.svg b/src/assets/icons/userlist.svg new file mode 100644 index 0000000..af6bf70 --- /dev/null +++ b/src/assets/icons/userlist.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/write.svg b/src/assets/icons/write.svg new file mode 100644 index 0000000..f4c41d1 --- /dev/null +++ b/src/assets/icons/write.svg @@ -0,0 +1,4 @@ + + + + From f66ae0a147d89da23fd4306206a213bd398ce34a Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 12:34:06 +0900 Subject: [PATCH 02/63] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=B6=88=EB=9F=AC=EC=98=A4=EB=8A=94=20API?= =?UTF-8?q?=20=EC=9A=94=EC=B2=AD=20=ED=95=A8=EC=88=98=EB=A5=BC=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/profile.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/apis/profile.ts diff --git a/src/apis/profile.ts b/src/apis/profile.ts new file mode 100644 index 0000000..35c619b --- /dev/null +++ b/src/apis/profile.ts @@ -0,0 +1,17 @@ +import axiosInstance from './api' + +interface ProfileResponse extends User {} + +async function getProfile(): Promise { + try { + const response = await axiosInstance.get( + `/users/${import.meta.env.VITE_USER_ID}` + ) + + return response.data + } catch (error) { + throw new Error('Error while fetching profile') + } +} + +export default getProfile From 4501358f9de9b418979f6d26e3ce6e943dde85d7 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 12:39:59 +0900 Subject: [PATCH 03/63] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20API=20=ED=98=B8=EC=B6=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `getProfile`: API를 사용하여 사용자 프로필 정보를 호출 - `useEffect`: 훅을 사용하여 컴포넌트가 마운트 될 때 API 호출 수행 - `useState`: 훅을 사용하여 사용자 정보 상태 관리 --- src/pages/Profile/index.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/pages/Profile/index.tsx diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx new file mode 100644 index 0000000..c88c1c6 --- /dev/null +++ b/src/pages/Profile/index.tsx @@ -0,0 +1,17 @@ +import getProfile from '@/apis/profile' +import { useEffect, useState } from 'react' + +function Profile() { + const [userInfo, setUserInfo] = useState(null) + + useEffect(() => { + const fetchUserInfo = async () => { + const data = await getProfile() + setUserInfo(data) + } + fetchUserInfo() + }, []) + return <> +} + +export default Profile From f7216a524a50ff0e8f668f20702a70cc0a390625 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 12:44:14 +0900 Subject: [PATCH 04/63] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EB=A3=A8=ED=8A=B8=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83=EC=9D=84=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `ProfileContainer`: 루트 레이아웃입니다. --- src/pages/Profile/index.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index c88c1c6..aa3c1de 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,9 +1,14 @@ import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' +import tw, { styled } from 'twin.macro' + +const ProfileContainer = styled.main` + ${tw`w-full h-screen relative`} +` function Profile() { const [userInfo, setUserInfo] = useState(null) - + useEffect(() => { const fetchUserInfo = async () => { const data = await getProfile() @@ -11,7 +16,8 @@ function Profile() { } fetchUserInfo() }, []) - return <> + + return } export default Profile From c8da1c6c8c421be1d750774683de515d9a870453 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 12:44:47 +0900 Subject: [PATCH 05/63] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=ED=97=A4=EB=8D=94=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `Header`: 뒤로가기 버튼이 존재하는 헤더 컴포넌트입니다. --- src/pages/Profile/index.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index aa3c1de..021435b 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -6,6 +6,10 @@ const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} ` +const Header = styled.header` + ${tw`w-full h-16 absolute top-0 left-0`} +` + function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -17,7 +21,18 @@ function Profile() { fetchUserInfo() }, []) - return + return ( + +
+ +
+
+ ) } export default Profile From 4b0d1a0df41367097084d8eca669f0fa6c926902 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 13:45:05 +0900 Subject: [PATCH 06/63] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `CoverImage`: 사용자 커버 이미지 컴포넌트입니다. - `DetailSection`: 사용자 프로필 이미지와 편집 버튼을 포함하는 컴포넌트입니다. --- src/pages/Profile/index.tsx | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 021435b..4c63364 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -10,6 +10,31 @@ const Header = styled.header` ${tw`w-full h-16 absolute top-0 left-0`} ` +const UserProfileSection = styled.section` + ${tw`w-full h-full`} +` + +const CoverImage = styled.img` + ${tw`w-full h-64 object-cover`} +` + +const UserProfileImage = styled.img` + ${tw`w-32 h-32 rounded-full object-cover z-10 bg-white`} +` + +const DetailSection = styled.div` + ${tw`mx-auto w-10/12 flex justify-between items-center relative -mt-16`} +` + +const Divider = styled.div` + ${tw`mx-auto w-10/12 h-[.3px] bg-[#000] my-6`} +` + +const EditButton = styled.button` + background: url('src/assets/icons/edit.svg') no-repeat center center; + ${tw`w-6 h-6 self-end mb-3`} +` + function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -31,6 +56,18 @@ function Profile() { /> + + + + + + + ) } From 2bcc3456daae2e315c26a4cc1caa6eb8348b0ffd Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 13:48:15 +0900 Subject: [PATCH 07/63] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A0=95=EB=B3=B4=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `UserProfileInfo`: 사용자 이름, 닉네임, 온라인 여부, 이메일 그리고 팔로우 컴포넌트를 포함합니다. --- src/App.tsx | 10 ++++-- src/apis/test.ts | 53 ++++++++++++++++++++++++++++ src/components/UploadImageButton.tsx | 53 ++++++++++++++++++++++++++++ src/pages/Profile/index.tsx | 38 ++++++++++++++++++++ 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/apis/test.ts create mode 100644 src/components/UploadImageButton.tsx diff --git a/src/App.tsx b/src/App.tsx index b4f6543..01a6f69 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,11 @@ +import Profile from '@/pages/Profile' + function App() { - return <>; + return ( + <> + + + ) } -export default App; +export default App diff --git a/src/apis/test.ts b/src/apis/test.ts new file mode 100644 index 0000000..e3c990b --- /dev/null +++ b/src/apis/test.ts @@ -0,0 +1,53 @@ +// const UserProfileInfoWrapper = styled.div` +// ${tw`flex justify-between gap-3`} +// ` + +// const UserProfileInfo = styled.div` +// ${tw`flex flex-col`} +// ` + +// const OnlineIndicator = styled.div(({ isOnline }) => [ +// tw`w-2 h-2 rounded-full bg-[crimson] self-end mb-1`, +// isOnline && tw`bg-[limegreen]` +// ]) + +// const FollowButtons = styled.div` +// ${tw`flex gap-2 font-semibold mt-3`} +// ` + +// const UserNameWrapper = styled.div` +// ${tw`flex items-center gap-2`} +// ` + +// +// +// +//

User

+//

+// {userInfo?.fullName} +//

+// +//
+//

{userInfo?.email}

+// +// +// +// +//
+//
+//
+// +// +//
+//
+//
\ No newline at end of file diff --git a/src/components/UploadImageButton.tsx b/src/components/UploadImageButton.tsx new file mode 100644 index 0000000..bb6e998 --- /dev/null +++ b/src/components/UploadImageButton.tsx @@ -0,0 +1,53 @@ +import { ChangeEvent, useCallback, useRef } from 'react' +import axiosInstance from '@/apis/api' +import { UPDATE_PROFILE_IMAGE_PATH } from '@/utils/api_paths' +import tw, { styled } from 'twin.macro' + +const FileInput = styled.input` + ${tw`file-input file-input-bordered w-full max-w-xs hidden`} +` +const UploadButton = styled.button` + ${tw`border border-black p-2 rounded-lg`} +` + +function UploadImageButton() { + const inputRef = useRef(null) + + const handleUploadImage = useCallback( + async (e: ChangeEvent, isCover: boolean) => { + if (!e.target.files) return + const formData = new FormData() + + formData.append('image', e.target.files[0]) + formData.append('isCover', isCover ? 'true' : 'false') + + await axiosInstance.post(UPDATE_PROFILE_IMAGE_PATH, formData, { + headers: { + Authorization: `Bearer ${import.meta.env.VITE_TOKEN}`, + 'Content-Type': 'multipart/form-data' + } + }) + }, + [] + ) + + const handleClickUploadButton = useCallback(() => { + if (!inputRef.current) return + + inputRef.current.click() + }, []) + + return ( + <> + handleUploadImage(e, false)} + /> + Upload + + ) +} + +export default UploadImageButton diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 4c63364..1b67084 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -35,6 +35,27 @@ const EditButton = styled.button` ${tw`w-6 h-6 self-end mb-3`} ` +const UserProfileInfoWrapper = styled.div` + ${tw`flex justify-between gap-3`} +` + +const UserProfileInfo = styled.div` + ${tw`flex flex-col`} +` + +const OnlineIndicator = styled.div(({ isOnline }) => [ + tw`w-2 h-2 rounded-full bg-[crimson] self-end mb-1`, + isOnline && tw`bg-[limegreen]` +]) + +const FollowButtons = styled.div` + ${tw`flex gap-2 font-semibold mt-3`} +` + +const UserNameWrapper = styled.div` + ${tw`flex items-center gap-2`} +` + function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -64,8 +85,25 @@ function Profile() { + + + +

User

+

+ {userInfo?.fullName} +

+ +
+

{userInfo?.email}

+ + + + +
+
+ From 930add3d2a06efa8a9861911c5727aa545325a7b Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 13:54:08 +0900 Subject: [PATCH 08/63] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=83=81=ED=98=B8=EC=9E=91?= =?UTF-8?q?=EC=9A=A9=20=EB=B2=84=ED=8A=BC=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `ButtonContainer`: 상호작용 버튼을 감싸는 루트 컴포넌트입니다. - `ChatButton`: 채팅 버튼입니다. - `FollowButton`: 팔로우 버튼입니다. --- src/pages/Profile/index.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 1b67084..987d945 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -56,6 +56,19 @@ const UserNameWrapper = styled.div` ${tw`flex items-center gap-2`} ` +const ButtonContainer = styled.div` + ${tw`self-center mb-3`} +` + +const ChatButton = styled.button` + background: url('src/assets/icons/chat.svg') no-repeat center center; + ${tw`w-6 h-6`} +` +const FollowButton = styled.button` + background: url('src/assets/icons/following.svg') no-repeat center center; + ${tw`w-6 h-6`} +` + function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -100,6 +113,12 @@ function Profile() { + +
+ + +
+
From c630f86362177da5493e1b0f3e08dcec21d79120 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 13:58:44 +0900 Subject: [PATCH 09/63] =?UTF-8?q?style:=20=EC=9E=84=EC=8B=9C=20=ED=8F=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83?= =?UTF-8?q?=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `PostSection`: 전체 포스트를 담고 있는 루트 레이아웃입니다. - `PostList`: 종류별 포스트들을 담고 있는 컴포넌트입니다. - `PostTitle`: 어떤 종류의 포스트인지 명시하는 제목 컴포넌트입니다. --- src/pages/Profile/index.tsx | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 987d945..3107dbe 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -69,6 +69,17 @@ const FollowButton = styled.button` ${tw`w-6 h-6`} ` +const PostSection = styled.section` + ${tw`mx-auto w-10/12 flex flex-col gap-6`} +` +const PostList = styled.div` + ${tw`h-96`} +` + +const PostTitle = styled.h1` + ${tw`text-lg font-bold mb-4`} +` + function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -122,8 +133,25 @@ function Profile() { - + + + 작성한 포스트 +
+ {userInfo?.posts && userInfo?.posts.length > 0 + ? '' + : '작성한 포스트가 없습니다.'} +
+
+ + 좋아요 한 포스트 +
+ {userInfo?.likes && userInfo?.likes.length > 0 + ? '' + : '좋아요 한 포스트가 없습니다.'} +
+
+
) From e3d4bd50fddd3591f4c8dec203aff1e81675d437 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 17:52:38 +0900 Subject: [PATCH 10/63] =?UTF-8?q?refactor:=20=ED=8F=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=84=B9=EC=85=98=20=EA=B4=80=EB=A0=A8=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EB=A5=BC=20PostList=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가독성을 개선하고 중복을 최소화하기 위해, 좋아요한 포스트와 작성한 포스트를 분리했습니다. - 어떤 포스트인지 listTitle prop으로 구분할 수 있습니다. --- src/pages/Profile/components/PostList.tsx | 24 +++++++++++++++++ src/pages/Profile/index.tsx | 32 +++++++---------------- 2 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 src/pages/Profile/components/PostList.tsx diff --git a/src/pages/Profile/components/PostList.tsx b/src/pages/Profile/components/PostList.tsx new file mode 100644 index 0000000..1ba0ef2 --- /dev/null +++ b/src/pages/Profile/components/PostList.tsx @@ -0,0 +1,24 @@ +import tw, { styled } from 'twin.macro' + +type PostListProps = { + posts: Post[] | Like[] | undefined + listTitle: string +} + +const PostListContainer = styled.div` + ${tw`h-96`} +` +const PostListTitle = styled.h1` + ${tw`text-lg font-bold mb-4`} +` + +function PostList({ posts, listTitle }: PostListProps) { + return ( + + {listTitle} + {posts && posts.length > 0 ? '' : 'No posts'} + + ) +} + +export default PostList diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 3107dbe..e56c06a 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,6 +1,7 @@ import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' +import PostList from './components/PostList' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} @@ -72,13 +73,6 @@ const FollowButton = styled.button` const PostSection = styled.section` ${tw`mx-auto w-10/12 flex flex-col gap-6`} ` -const PostList = styled.div` - ${tw`h-96`} -` - -const PostTitle = styled.h1` - ${tw`text-lg font-bold mb-4`} -` function Profile() { const [userInfo, setUserInfo] = useState(null) @@ -135,22 +129,14 @@ function Profile() { - - 작성한 포스트 -
- {userInfo?.posts && userInfo?.posts.length > 0 - ? '' - : '작성한 포스트가 없습니다.'} -
-
- - 좋아요 한 포스트 -
- {userInfo?.likes && userInfo?.likes.length > 0 - ? '' - : '좋아요 한 포스트가 없습니다.'} -
-
+ +
From 3e09a69b1dde84630c7731096eb322857209277c Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 17:56:48 +0900 Subject: [PATCH 11/63] =?UTF-8?q?refactor:=20=EC=9D=B4=EC=A0=84=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=8C=EC=95=84=EA=B0=80=EA=B8=B0=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=EC=9D=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가독성을 위해 컴포넌트로 분리했습니다. --- src/pages/Profile/index.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index e56c06a..ac7ffe2 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -11,6 +11,10 @@ const Header = styled.header` ${tw`w-full h-16 absolute top-0 left-0`} ` +const PrevButton = styled.header` + background: url('src/assets/icons/prev_white.svg') no-repeat center center; + ${tw`w-12 h-12`} +` const UserProfileSection = styled.section` ${tw`w-full h-full`} ` @@ -88,12 +92,7 @@ function Profile() { return (
- +
From add60eac87a1c60cc07109273550fe19443b245f Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 18:12:38 +0900 Subject: [PATCH 12/63] =?UTF-8?q?refactor:=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 헤더는 프로필 편집 페이지에서도 사용됩니다. --- src/pages/Profile/components/Header.tsx | 20 ++++++++++++++++++++ src/pages/Profile/index.tsx | 13 ++----------- 2 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 src/pages/Profile/components/Header.tsx diff --git a/src/pages/Profile/components/Header.tsx b/src/pages/Profile/components/Header.tsx new file mode 100644 index 0000000..0923e15 --- /dev/null +++ b/src/pages/Profile/components/Header.tsx @@ -0,0 +1,20 @@ +import tw, { styled } from 'twin.macro' + +const HeaderContainer = styled.header` + ${tw`w-full h-16 absolute top-0 left-0`} +` + +const PrevButton = styled.button` + background: url('src/assets/icons/prev_white.svg') no-repeat center center; + ${tw`w-12 h-12`} +` + +function Header() { + return ( + + + + ) +} + +export default Header diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index ac7ffe2..a01df05 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -2,19 +2,12 @@ import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' import PostList from './components/PostList' +import Header from './components/Header' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} ` -const Header = styled.header` - ${tw`w-full h-16 absolute top-0 left-0`} -` - -const PrevButton = styled.header` - background: url('src/assets/icons/prev_white.svg') no-repeat center center; - ${tw`w-12 h-12`} -` const UserProfileSection = styled.section` ${tw`w-full h-full`} ` @@ -91,9 +84,7 @@ function Profile() { return ( -
- -
+
From 0609358a1cbdd03bc884adca152f0a655495117f Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 19:24:43 +0900 Subject: [PATCH 13/63] =?UTF-8?q?refactor:=20API=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 하드코딩된 경로를 미리 지정한 경로로 수정했습니다. --- src/apis/profile.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apis/profile.ts b/src/apis/profile.ts index 35c619b..7335bb8 100644 --- a/src/apis/profile.ts +++ b/src/apis/profile.ts @@ -1,3 +1,4 @@ +import { GET_USER_PROFILE_PATH } from '@/utils/api_paths' import axiosInstance from './api' interface ProfileResponse extends User {} @@ -5,7 +6,7 @@ interface ProfileResponse extends User {} async function getProfile(): Promise { try { const response = await axiosInstance.get( - `/users/${import.meta.env.VITE_USER_ID}` + `${GET_USER_PROFILE_PATH}/${import.meta.env.VITE_USER_ID}` ) return response.data From 9a669637e8cb6ea63b7b45aaf2c178780e3c8ea4 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 19:25:10 +0900 Subject: [PATCH 14/63] =?UTF-8?q?remove:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20=EC=9E=91=EC=84=B1=ED=95=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EC=9D=84=20=EC=82=AD=EC=A0=9C=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/test.ts | 53 ------------------------------------------------ 1 file changed, 53 deletions(-) delete mode 100644 src/apis/test.ts diff --git a/src/apis/test.ts b/src/apis/test.ts deleted file mode 100644 index e3c990b..0000000 --- a/src/apis/test.ts +++ /dev/null @@ -1,53 +0,0 @@ -// const UserProfileInfoWrapper = styled.div` -// ${tw`flex justify-between gap-3`} -// ` - -// const UserProfileInfo = styled.div` -// ${tw`flex flex-col`} -// ` - -// const OnlineIndicator = styled.div(({ isOnline }) => [ -// tw`w-2 h-2 rounded-full bg-[crimson] self-end mb-1`, -// isOnline && tw`bg-[limegreen]` -// ]) - -// const FollowButtons = styled.div` -// ${tw`flex gap-2 font-semibold mt-3`} -// ` - -// const UserNameWrapper = styled.div` -// ${tw`flex items-center gap-2`} -// ` - -// -// -// -//

User

-//

-// {userInfo?.fullName} -//

-// -//
-//

{userInfo?.email}

-// -// -// -// -//
-//
-//
-// -// -//
-//
-//
\ No newline at end of file From 3bcd70192d0efbc06c5647f5e56af93fb4c1e849 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 19:33:19 +0900 Subject: [PATCH 15/63] =?UTF-8?q?refactor:=20=EB=B2=84=ED=8A=BC=EC=9D=84?= =?UTF-8?q?=20=EB=8B=B4=EB=8A=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `FollowButtons`: FollowButton과 유사하여 삭제했습니다. ButtonContainer로 대체했습니다. - ButtonContainer의 스타일을 수정하여, 중복을 최소화했습니다. --- src/pages/Profile/index.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index a01df05..5f5951f 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -46,16 +46,12 @@ const OnlineIndicator = styled.div(({ isOnline }) => [ isOnline && tw`bg-[limegreen]` ]) -const FollowButtons = styled.div` - ${tw`flex gap-2 font-semibold mt-3`} -` - const UserNameWrapper = styled.div` ${tw`flex items-center gap-2`} ` const ButtonContainer = styled.div` - ${tw`self-center mb-3`} + ${tw`flex gap-2`} ` const ChatButton = styled.button` @@ -103,16 +99,14 @@ function Profile() {

{userInfo?.email}

- + - + - -
- - -
+ + + From a552f9f920339a6bad40c77da2145bf30570645a Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Fri, 29 Dec 2023 19:40:16 +0900 Subject: [PATCH 16/63] =?UTF-8?q?feat:=20=EB=82=B4=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=EC=9D=B8=EC=A7=80=20=ED=99=95=EC=9D=B8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 내 프로필인지에 따라 특정 버튼을 활성화, 비활성화합니다. --- src/pages/Profile/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 5f5951f..177b972 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -69,6 +69,7 @@ const PostSection = styled.section` function Profile() { const [userInfo, setUserInfo] = useState(null) + const isMyProfile = userInfo?._id === import.meta.env.VITE_USER_ID useEffect(() => { const fetchUserInfo = async () => { @@ -87,7 +88,7 @@ function Profile() { From 92a445697d15906fa83185bdf8faf8a469f501dd Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sat, 30 Dec 2023 18:46:07 +0900 Subject: [PATCH 17/63] =?UTF-8?q?feat:=20FormData=20=ED=98=95=EC=8B=9D?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=98=EB=8A=94=20=ED=95=A8=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 커버, 프로필 이미지는 isCover의 값에 따라 달라집니다. - type에 따라 사용되는 곳이 달라집니다. --- src/utils/handleImageFormData.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/utils/handleImageFormData.ts diff --git a/src/utils/handleImageFormData.ts b/src/utils/handleImageFormData.ts new file mode 100644 index 0000000..1a57b26 --- /dev/null +++ b/src/utils/handleImageFormData.ts @@ -0,0 +1,17 @@ +interface ImageFormData { + imageFile: File + type: 'Profile' | 'Post' + isCover?: boolean +} + +function handleImageFormData({ imageFile, type, isCover }: ImageFormData): FormData { + const formData = new FormData() + + formData.append('image', imageFile) + + if (type === 'Profile') formData.append('isCover', String(isCover)) + + return formData +} + +export default handleImageFormData From b41389864080cc6857a6592d37f956ede2d56ebe Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sat, 30 Dec 2023 18:46:58 +0900 Subject: [PATCH 18/63] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84,=20?= =?UTF-8?q?=EC=BB=A4=EB=B2=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20API=EB=A5=BC=20=ED=98=B8=EC=B6=9C=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/uploadImage.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/apis/uploadImage.ts diff --git a/src/apis/uploadImage.ts b/src/apis/uploadImage.ts new file mode 100644 index 0000000..618afb6 --- /dev/null +++ b/src/apis/uploadImage.ts @@ -0,0 +1,22 @@ +import { UPDATE_PROFILE_IMAGE_PATH } from '@/utils/api_paths' +import axiosInstance from './api' + +async function uploadImage(formData: FormData) { + try { + const response = await axiosInstance.post( + UPDATE_PROFILE_IMAGE_PATH, + formData, + { + headers: { + Authorization: `Bearer ${import.meta.env.VITE_TOKEN}`, + 'Content-Type': 'multipart/form-data' + } + } + ) + return response.data + } catch (error) { + throw new Error('Error while uploading image') + } +} + +export default uploadImage From 25f300de6c182c40b18d4f99b1d4f771636d1fe8 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sat, 30 Dec 2023 18:49:33 +0900 Subject: [PATCH 19/63] =?UTF-8?q?style:=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - svg를 jsx로 반환합니다. --- src/pages/Profile/components/FollowButton.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/pages/Profile/components/FollowButton.tsx diff --git a/src/pages/Profile/components/FollowButton.tsx b/src/pages/Profile/components/FollowButton.tsx new file mode 100644 index 0000000..a80e6f0 --- /dev/null +++ b/src/pages/Profile/components/FollowButton.tsx @@ -0,0 +1,21 @@ +// icon:heart | Feathericons https://feathericons.com/ | Cole Bemis +import * as React from 'react' + +function FollowButton(props: React.SVGProps) { + return ( + + + + ) +} + +export default FollowButton From 794d6a547edc4b562fea3220f7a9b4dc5b947563 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 14:56:55 +0900 Subject: [PATCH 20/63] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컴포넌트를 분리하여 코드의 가독성을 높였습니다. --- .../Profile/components/ButtonContainer.tsx | 7 ++ .../Profile/components/UserProfileImage.tsx | 30 ++++++ .../Profile/components/UserProfileInfo.tsx | 81 ++++++++++++++++ src/pages/Profile/index.tsx | 97 ++++++------------- 4 files changed, 147 insertions(+), 68 deletions(-) create mode 100644 src/pages/Profile/components/ButtonContainer.tsx create mode 100644 src/pages/Profile/components/UserProfileImage.tsx create mode 100644 src/pages/Profile/components/UserProfileInfo.tsx diff --git a/src/pages/Profile/components/ButtonContainer.tsx b/src/pages/Profile/components/ButtonContainer.tsx new file mode 100644 index 0000000..d6ccb23 --- /dev/null +++ b/src/pages/Profile/components/ButtonContainer.tsx @@ -0,0 +1,7 @@ +import tw, { styled } from 'twin.macro' + +const ButtonContainer = styled.div` + ${tw`flex gap-2`} +` + +export default ButtonContainer diff --git a/src/pages/Profile/components/UserProfileImage.tsx b/src/pages/Profile/components/UserProfileImage.tsx new file mode 100644 index 0000000..c5f0aed --- /dev/null +++ b/src/pages/Profile/components/UserProfileImage.tsx @@ -0,0 +1,30 @@ +import tw, { styled } from 'twin.macro' + +interface UserProfileImageProps { + imgSrc?: string + isMyProfile: boolean +} + +const UserProfileImageWrapper = styled.div` + ${tw`w-full flex justify-between`} +` + +const ProfileImage = styled.img` + ${tw`w-32 h-32 rounded-full object-cover z-10 bg-white`} +` + +const EditButton = styled.button` + background: url('src/assets/icons/edit.svg') no-repeat center center; + ${tw`w-6 h-6 self-end mb-3`} +` + +function UserProfileImage({ imgSrc, isMyProfile }: UserProfileImageProps) { + return ( + + + {isMyProfile && } + + ) +} + +export default UserProfileImage diff --git a/src/pages/Profile/components/UserProfileInfo.tsx b/src/pages/Profile/components/UserProfileInfo.tsx new file mode 100644 index 0000000..c6041d3 --- /dev/null +++ b/src/pages/Profile/components/UserProfileInfo.tsx @@ -0,0 +1,81 @@ +import tw, { styled } from 'twin.macro' +import ButtonContainer from './ButtonContainer' +import FollowButton from './FollowButton' + +interface UserProfileInfoProps { + fullName?: string + userName?: string + email?: string + isOnline?: boolean + followers?: Follow[] + following?: Following[] + isMyProfile: boolean + isFollowed: boolean + onClickFollowButton: () => void +} + +const UserProfileInfoWrapper = styled.div` + ${tw`flex justify-between gap-3`} +` + +const ProfileInfo = styled.div` + ${tw`flex flex-col`} +` + +const UserNameWrapper = styled.div` + ${tw`flex items-center gap-2`} +` + +const OnlineIndicator = styled.div(({ isOnline }) => [ + tw`w-2 h-2 rounded-full bg-[crimson] self-end mb-1`, + isOnline && tw`bg-[limegreen]` +]) + +const ChatButton = styled.button` + background: url('src/assets/icons/chat.svg') no-repeat center center; + ${tw`w-6 h-6`} +` + +function UserProfileInfo({ + fullName, + userName, + email, + isOnline, + followers, + following, + isMyProfile, + isFollowed, + onClickFollowButton +}: UserProfileInfoProps) { + return ( + + + +

{userName || 'User'}

+

{fullName}

+ +
+

{email}

+ + + + +
+ + + {!isMyProfile && isFollowed && ( + + )} + {!isMyProfile && !isFollowed && ( + + )} + +
+ ) +} + +export default UserProfileInfo diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 177b972..d205c14 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,8 +1,12 @@ import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' -import PostList from './components/PostList' +import UserProfileImage from './components/UserProfileImage' +import UserProfileInfo from './components/UserProfileInfo' +import ButtonContainer from './components/ButtonContainer' import Header from './components/Header' +import FollowButton from './components/FollowButton' +import PostList from './components/PostList' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} @@ -16,10 +20,6 @@ const CoverImage = styled.img` ${tw`w-full h-64 object-cover`} ` -const UserProfileImage = styled.img` - ${tw`w-32 h-32 rounded-full object-cover z-10 bg-white`} -` - const DetailSection = styled.div` ${tw`mx-auto w-10/12 flex justify-between items-center relative -mt-16`} ` @@ -28,55 +28,27 @@ const Divider = styled.div` ${tw`mx-auto w-10/12 h-[.3px] bg-[#000] my-6`} ` -const EditButton = styled.button` - background: url('src/assets/icons/edit.svg') no-repeat center center; - ${tw`w-6 h-6 self-end mb-3`} -` - -const UserProfileInfoWrapper = styled.div` - ${tw`flex justify-between gap-3`} -` - -const UserProfileInfo = styled.div` - ${tw`flex flex-col`} -` - -const OnlineIndicator = styled.div(({ isOnline }) => [ - tw`w-2 h-2 rounded-full bg-[crimson] self-end mb-1`, - isOnline && tw`bg-[limegreen]` -]) - -const UserNameWrapper = styled.div` - ${tw`flex items-center gap-2`} -` - -const ButtonContainer = styled.div` - ${tw`flex gap-2`} -` - -const ChatButton = styled.button` - background: url('src/assets/icons/chat.svg') no-repeat center center; - ${tw`w-6 h-6`} -` -const FollowButton = styled.button` - background: url('src/assets/icons/following.svg') no-repeat center center; - ${tw`w-6 h-6`} -` - const PostSection = styled.section` ${tw`mx-auto w-10/12 flex flex-col gap-6`} ` function Profile() { - const [userInfo, setUserInfo] = useState(null) + const [userInfo, setUserInfo] = useState() const isMyProfile = userInfo?._id === import.meta.env.VITE_USER_ID + const [myInfo, setMyInfo] = useState(null) useEffect(() => { const fetchUserInfo = async () => { - const data = await getProfile() + const data = await getProfile(import.meta.env.VITE_ADMIN_ID) setUserInfo(data) } fetchUserInfo() + + const fetchMyProfile = async () => { + const data = await getProfile(import.meta.env.VITE_USER_ID) + setMyInfo(data) + } + fetchMyProfile() }, []) return ( @@ -85,32 +57,21 @@ function Profile() { - +
+ + +
From a76cba683db8728f6aa6ad65b51e928343e672ac Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 14:58:57 +0900 Subject: [PATCH 21/63] =?UTF-8?q?feat:=20=ED=8C=94=EB=A1=9C=EC=9A=B0,=20?= =?UTF-8?q?=ED=8C=94=EB=A1=9C=EC=9A=B0=20=EC=B7=A8=EC=86=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 나의 프로필 정보를 불러와서 해당 유저를 팔로우 하는지 확인합니다. - 팔로우 버튼을 클릭하여 팔로우, 팔로우 취소할 수 있게 했습니다. --- src/pages/Profile/index.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index d205c14..565500a 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -3,9 +3,7 @@ import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' import UserProfileImage from './components/UserProfileImage' import UserProfileInfo from './components/UserProfileInfo' -import ButtonContainer from './components/ButtonContainer' import Header from './components/Header' -import FollowButton from './components/FollowButton' import PostList from './components/PostList' const ProfileContainer = styled.main` @@ -36,6 +34,7 @@ function Profile() { const [userInfo, setUserInfo] = useState() const isMyProfile = userInfo?._id === import.meta.env.VITE_USER_ID const [myInfo, setMyInfo] = useState(null) + const [isFollowed, setIsFollowed] = useState(false) useEffect(() => { const fetchUserInfo = async () => { @@ -51,6 +50,20 @@ function Profile() { fetchMyProfile() }, []) + useEffect(() => { + const checkIsFollowedUser = () => { + const res = myInfo?.following.some( + (item) => item.user === import.meta.env.VITE_ADMIN_ID + ) + setIsFollowed(res!) + } + checkIsFollowedUser() + }, [myInfo]) + + const handleClickFollowButton = () => { + setIsFollowed((prev) => !prev) + } + return (
@@ -70,6 +83,8 @@ function Profile() { followers={userInfo?.followers} following={userInfo?.following} isMyProfile={isMyProfile} + isFollowed={isFollowed} + onClickFollowButton={handleClickFollowButton} /> From 04fb720c82591d66bd9808d60cfe83bd1d15c1f0 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 14:59:50 +0900 Subject: [PATCH 22/63] =?UTF-8?q?style:=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9D=98=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 팔로우하지 않을 경우 아이콘의 너비와 높이를 팔로우 했을 경우 아이콘의 너비와 높이로 통일 했습니다. --- src/pages/Profile/components/UserProfileInfo.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/components/UserProfileInfo.tsx b/src/pages/Profile/components/UserProfileInfo.tsx index c6041d3..d52b606 100644 --- a/src/pages/Profile/components/UserProfileInfo.tsx +++ b/src/pages/Profile/components/UserProfileInfo.tsx @@ -71,7 +71,10 @@ function UserProfileInfo({ /> )} {!isMyProfile && !isFollowed && ( - + )} From 332b0ad06c6cd32cce6a37c4a2b4748aa325ec39 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 15:05:29 +0900 Subject: [PATCH 23/63] =?UTF-8?q?modify:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=ED=95=A8=EC=88=98=EC=97=90=20=EC=9D=B8=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - id인자를 추가하여, 특정 id를 가진 유저의 프로필 정보를 가져올 수 있습니다. --- src/apis/profile.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apis/profile.ts b/src/apis/profile.ts index 7335bb8..6fa6aca 100644 --- a/src/apis/profile.ts +++ b/src/apis/profile.ts @@ -3,10 +3,10 @@ import axiosInstance from './api' interface ProfileResponse extends User {} -async function getProfile(): Promise { +async function getProfile(id: string): Promise { try { const response = await axiosInstance.get( - `${GET_USER_PROFILE_PATH}/${import.meta.env.VITE_USER_ID}` + `${GET_USER_PROFILE_PATH}/${id}` ) return response.data From 227b0077714372b3fb4cf3955fb65fb83e7f5b5b Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 15:06:36 +0900 Subject: [PATCH 24/63] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프로필 페이지에서는 사용하지 않는 이미지 업로드 버튼을 삭제했습니다. --- src/components/UploadImageButton.tsx | 53 ---------------------------- 1 file changed, 53 deletions(-) delete mode 100644 src/components/UploadImageButton.tsx diff --git a/src/components/UploadImageButton.tsx b/src/components/UploadImageButton.tsx deleted file mode 100644 index bb6e998..0000000 --- a/src/components/UploadImageButton.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { ChangeEvent, useCallback, useRef } from 'react' -import axiosInstance from '@/apis/api' -import { UPDATE_PROFILE_IMAGE_PATH } from '@/utils/api_paths' -import tw, { styled } from 'twin.macro' - -const FileInput = styled.input` - ${tw`file-input file-input-bordered w-full max-w-xs hidden`} -` -const UploadButton = styled.button` - ${tw`border border-black p-2 rounded-lg`} -` - -function UploadImageButton() { - const inputRef = useRef(null) - - const handleUploadImage = useCallback( - async (e: ChangeEvent, isCover: boolean) => { - if (!e.target.files) return - const formData = new FormData() - - formData.append('image', e.target.files[0]) - formData.append('isCover', isCover ? 'true' : 'false') - - await axiosInstance.post(UPDATE_PROFILE_IMAGE_PATH, formData, { - headers: { - Authorization: `Bearer ${import.meta.env.VITE_TOKEN}`, - 'Content-Type': 'multipart/form-data' - } - }) - }, - [] - ) - - const handleClickUploadButton = useCallback(() => { - if (!inputRef.current) return - - inputRef.current.click() - }, []) - - return ( - <> - handleUploadImage(e, false)} - /> - Upload - - ) -} - -export default UploadImageButton From 76cf62788203d41b6b88d7a75ff7d65879f2039a Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 15:08:10 +0900 Subject: [PATCH 25/63] =?UTF-8?q?fix:=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20import=EB=A5=BC=20=ED=95=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 01a6f69..37e1ff8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import Profile from '@/pages/Profile' +import Profile from '@/pages/profile' function App() { return ( From ae608e78c444d984c4c2cf12c846281df0c0e3c2 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 15:12:55 +0900 Subject: [PATCH 26/63] =?UTF-8?q?rename:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프로필 편집 페이지에 사용되는 컴포넌트와 구분하기 위해, profile 폴더로 컴포넌트의 위치를 변경했습니다. --- .../Profile/components/{ => profile}/ButtonContainer.tsx | 0 src/pages/Profile/components/{ => profile}/FollowButton.tsx | 0 src/pages/Profile/components/{ => profile}/PostList.tsx | 0 .../Profile/components/{ => profile}/UserProfileImage.tsx | 0 .../Profile/components/{ => profile}/UserProfileInfo.tsx | 0 src/pages/Profile/index.tsx | 6 +++--- 6 files changed, 3 insertions(+), 3 deletions(-) rename src/pages/Profile/components/{ => profile}/ButtonContainer.tsx (100%) rename src/pages/Profile/components/{ => profile}/FollowButton.tsx (100%) rename src/pages/Profile/components/{ => profile}/PostList.tsx (100%) rename src/pages/Profile/components/{ => profile}/UserProfileImage.tsx (100%) rename src/pages/Profile/components/{ => profile}/UserProfileInfo.tsx (100%) diff --git a/src/pages/Profile/components/ButtonContainer.tsx b/src/pages/Profile/components/profile/ButtonContainer.tsx similarity index 100% rename from src/pages/Profile/components/ButtonContainer.tsx rename to src/pages/Profile/components/profile/ButtonContainer.tsx diff --git a/src/pages/Profile/components/FollowButton.tsx b/src/pages/Profile/components/profile/FollowButton.tsx similarity index 100% rename from src/pages/Profile/components/FollowButton.tsx rename to src/pages/Profile/components/profile/FollowButton.tsx diff --git a/src/pages/Profile/components/PostList.tsx b/src/pages/Profile/components/profile/PostList.tsx similarity index 100% rename from src/pages/Profile/components/PostList.tsx rename to src/pages/Profile/components/profile/PostList.tsx diff --git a/src/pages/Profile/components/UserProfileImage.tsx b/src/pages/Profile/components/profile/UserProfileImage.tsx similarity index 100% rename from src/pages/Profile/components/UserProfileImage.tsx rename to src/pages/Profile/components/profile/UserProfileImage.tsx diff --git a/src/pages/Profile/components/UserProfileInfo.tsx b/src/pages/Profile/components/profile/UserProfileInfo.tsx similarity index 100% rename from src/pages/Profile/components/UserProfileInfo.tsx rename to src/pages/Profile/components/profile/UserProfileInfo.tsx diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 565500a..2095351 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,10 +1,10 @@ import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' -import UserProfileImage from './components/UserProfileImage' -import UserProfileInfo from './components/UserProfileInfo' +import UserProfileImage from './components/profile/UserProfileImage' +import UserProfileInfo from './components/profile/UserProfileInfo' import Header from './components/Header' -import PostList from './components/PostList' +import PostList from './components/profile/PostList' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} From b95b2fd8dc9f76315a449417d46e42b1e72f1a3b Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 16:17:35 +0900 Subject: [PATCH 27/63] =?UTF-8?q?style:=20=ED=8E=B8=EC=A7=91=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/components/EditIcon.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/pages/Profile/components/EditIcon.tsx diff --git a/src/pages/Profile/components/EditIcon.tsx b/src/pages/Profile/components/EditIcon.tsx new file mode 100644 index 0000000..cdcc138 --- /dev/null +++ b/src/pages/Profile/components/EditIcon.tsx @@ -0,0 +1,22 @@ +// icon:edit | Feathericons https://feathericons.com/ | Cole Bemis +import * as React from 'react' + +function EditIcon(props: React.SVGProps) { + return ( + + + + + ) +} + +export default EditIcon From 3191c2dc6f571287857e8fc70e3fafa2de566a0c Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 16:19:04 +0900 Subject: [PATCH 28/63] =?UTF-8?q?style:=20=EC=9E=84=EC=8B=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=ED=8E=B8=EC=A7=91=20Drawer=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 데이터 바인딩이 되지 않은 임시 컴포넌트 입니다. --- .../profile-edit-drawer/CoverImage.tsx | 23 ++++++ .../components/profile-edit-drawer/Drawer.tsx | 42 ++++++++++ .../profile-edit-drawer/DrawerSide.tsx | 76 +++++++++++++++++++ .../profile-edit-drawer/ProfileImage.tsx | 23 ++++++ .../profile-edit-drawer/ProfileInput.tsx | 40 ++++++++++ 5 files changed, 204 insertions(+) create mode 100644 src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx create mode 100644 src/pages/Profile/components/profile-edit-drawer/Drawer.tsx create mode 100644 src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx create mode 100644 src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx create mode 100644 src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx diff --git a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx new file mode 100644 index 0000000..ad4e94a --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx @@ -0,0 +1,23 @@ +import tw, { styled } from 'twin.macro' +import EditIcon from '../EditIcon' + +const CoverImageWrapper = styled.div` + ${tw`relative`} +` + +function CoverImage() { + return ( + + profile + + + ) +} + +export default CoverImage diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx new file mode 100644 index 0000000..4000b64 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -0,0 +1,42 @@ +import tw, { styled } from 'twin.macro' +import { useState } from 'react' +import DrawerSide from './DrawerSide' + +const DrawerContainer = styled.div`` + +const DrawerControl = styled.input`` + +const DrawerContent = styled.div` + ${tw`flex flex-col items-center justify-center`} +` + +function Drawer() { + const [isOpen, setIsOpen] = useState(false) + + const toggleDrawer = () => { + setIsOpen(!isOpen) + } + + return ( + + + + {/* Page content here -> Profile Page */} + + + + + ) +} + +export default Drawer diff --git a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx new file mode 100644 index 0000000..ebb9835 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx @@ -0,0 +1,76 @@ +import tw, { styled } from 'twin.macro' +import ProfileInput from './ProfileInput' +import CoverImage from './CoverImage' +import ProfileImage from './ProfileImage' + +const ProfileDrawerSide = styled.div`` + +const HeaderContainer = styled.header` + ${tw`w-full h-16 absolute top-0 left-0 hover:bg-inherit`} +` + +const PrevButton = styled.button` + background: url('src/assets/icons/prev_white.svg') no-repeat center center; + ${tw`w-12 h-12 drawer-toggle opacity-100`} +` + +const Container = styled.div` + ${tw`w-full min-h-full`} +` + +const DetailSection = styled.div` + ${tw`mx-auto w-10/12 flex flex-col justify-between items-center relative -mt-16`} +` + +const InputWrapper = styled.div` + ${tw`w-full mb-36 flex flex-col gap-3`} +` + +const ConfirmButton = styled.div` + padding: 10px 20px; + border-radius: 30px; + background: #fff; + box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1); +` + +function DrawerSide() { + return ( + + + {}} /> + + + + + + + {}} + /> + {}} + /> + {}} + /> + + 수정하기 + + + + ) +} + +export default DrawerSide diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx new file mode 100644 index 0000000..f43ac93 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx @@ -0,0 +1,23 @@ +import tw, { styled } from 'twin.macro' +import EditIcon from '../EditIcon' + +const ProfileImageWrapper = styled.div` + ${tw`relative overflow-hidden rounded-full`} +` + +function ProfileImage() { + return ( + + profile + + + ) +} + +export default ProfileImage diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx new file mode 100644 index 0000000..46538c3 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import tw, { styled } from 'twin.macro' + +interface InputProps { + labelName: string + value: string + placeholder: string + type: string + onChangeInput: (e: React.ChangeEvent) => void +} + +const Input = styled.input` + ${tw`w-full border-b outline-none focus:border-brand-primary px-3 py-2`} +` + +const Label = styled.label` + ${tw`label`} +` + +function ProfileInput({ + labelName, + value, + placeholder, + type, + onChangeInput +}: InputProps) { + return ( +
+ + +
+ ) +} + +export default ProfileInput From 0dfb750c6aa1ddd23f3683540582adedfef75c2c Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 19:41:48 +0900 Subject: [PATCH 29/63] =?UTF-8?q?refactor:=20=EB=B3=80=EC=88=98,=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - label의 이름을 의미가 명확하게 변경했습니다. - toggleDrawer의 이름에 handle prefix를 추가했습니다. --- .../Profile/components/profile-edit-drawer/Drawer.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index 4000b64..4f4c8c6 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -13,7 +13,7 @@ const DrawerContent = styled.div` function Drawer() { const [isOpen, setIsOpen] = useState(false) - const toggleDrawer = () => { + const handleToggleDrawer = () => { setIsOpen(!isOpen) } @@ -24,15 +24,11 @@ function Drawer() { type="checkbox" className="drawer-toggle" checked={isOpen} - onChange={toggleDrawer} + onChange={handleToggleDrawer} /> {/* Page content here -> Profile Page */} - + Open From 089315344d3bfff96f07b837e1c3221896e0887c Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 19:43:37 +0900 Subject: [PATCH 30/63] =?UTF-8?q?refactor:=20input=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 3개의 input 필드를 form으로 관리합니다. - 수정 버튼을 form의 submit을 수행하는 버튼으로 변경했습니다. --- .../profile-edit-drawer/DrawerSide.tsx | 38 +---------- .../profile-edit-drawer/ProfileInputForm.tsx | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+), 36 deletions(-) create mode 100644 src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx diff --git a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx index ebb9835..9eb3554 100644 --- a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx @@ -1,7 +1,7 @@ import tw, { styled } from 'twin.macro' -import ProfileInput from './ProfileInput' import CoverImage from './CoverImage' import ProfileImage from './ProfileImage' +import ProfileInputForm from './ProfileInputForm' const ProfileDrawerSide = styled.div`` @@ -22,17 +22,6 @@ const DetailSection = styled.div` ${tw`mx-auto w-10/12 flex flex-col justify-between items-center relative -mt-16`} ` -const InputWrapper = styled.div` - ${tw`w-full mb-36 flex flex-col gap-3`} -` - -const ConfirmButton = styled.div` - padding: 10px 20px; - border-radius: 30px; - background: #fff; - box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1); -` - function DrawerSide() { return ( @@ -43,30 +32,7 @@ function DrawerSide() { - - {}} - /> - {}} - /> - {}} - /> - - 수정하기 + diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx new file mode 100644 index 0000000..9df5ab0 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx @@ -0,0 +1,64 @@ +import React, { useState } from 'react' +import tw, { styled } from 'twin.macro' +import ProfileInput from './ProfileInput' + +const Form = styled.form` + ${tw`w-full mb-36 flex flex-col gap-3`} +` + +const SubmitButton = styled.button` + padding: 10px 20px; + border-radius: 30px; + background: #fff; + box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1); +` + +function ProfileInputForm() { + const [userName, setUserName] = useState('') + const [fullName, setFullName] = useState('') + const [password, setPassword] = useState('') + + const handleChangeUserName = (e: React.ChangeEvent) => { + setUserName(e.target.value) + } + const handleChangeFullName = (e: React.ChangeEvent) => { + setFullName(e.target.value) + } + + const handleChangePassword = (e: React.ChangeEvent) => { + setPassword(e.target.value) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + } + + return ( +
+ + + + 수정하기 + + ) +} + +export default ProfileInputForm From 7d4b98005ccce6eb720e7b8e123b4b90cde9ae4f Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 19:59:19 +0900 Subject: [PATCH 31/63] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=20=ED=8E=B8=EC=A7=91=20=EB=B2=84=ED=8A=BC=EC=9D=98=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 UserProfileImage에서 상위 컴포넌트로 선언 위치를 변경했습니다. - 프로필 편집 페이지로 넘어가는 로직을 단순화 할 수 있습니다. --- .../components/profile/UserProfileImage.tsx | 12 ++--------- src/pages/Profile/index.tsx | 21 +++++++++++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/pages/Profile/components/profile/UserProfileImage.tsx b/src/pages/Profile/components/profile/UserProfileImage.tsx index c5f0aed..e99dac6 100644 --- a/src/pages/Profile/components/profile/UserProfileImage.tsx +++ b/src/pages/Profile/components/profile/UserProfileImage.tsx @@ -5,24 +5,16 @@ interface UserProfileImageProps { isMyProfile: boolean } -const UserProfileImageWrapper = styled.div` - ${tw`w-full flex justify-between`} -` +const UserProfileImageWrapper = styled.div`` const ProfileImage = styled.img` ${tw`w-32 h-32 rounded-full object-cover z-10 bg-white`} ` -const EditButton = styled.button` - background: url('src/assets/icons/edit.svg') no-repeat center center; - ${tw`w-6 h-6 self-end mb-3`} -` - -function UserProfileImage({ imgSrc, isMyProfile }: UserProfileImageProps) { +function UserProfileImage({ imgSrc }: UserProfileImageProps) { return ( - {isMyProfile && } ) } diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 2095351..0013446 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -30,9 +30,14 @@ const PostSection = styled.section` ${tw`mx-auto w-10/12 flex flex-col gap-6`} ` +const EditButton = styled.button` + background: url('src/assets/icons/edit.svg') no-repeat center center; + ${tw`w-6 h-6 self-end mb-3`} +` + function Profile() { const [userInfo, setUserInfo] = useState() - const isMyProfile = userInfo?._id === import.meta.env.VITE_USER_ID + const isMyProfile = userInfo?._id === import.meta.env.VITE_ADMIN_ID const [myInfo, setMyInfo] = useState(null) const [isFollowed, setIsFollowed] = useState(false) @@ -44,7 +49,7 @@ function Profile() { fetchUserInfo() const fetchMyProfile = async () => { - const data = await getProfile(import.meta.env.VITE_USER_ID) + const data = await getProfile(import.meta.env.VITE_ADMIN_ID) setMyInfo(data) } fetchMyProfile() @@ -71,10 +76,14 @@ function Profile() {
- +
+ + {isMyProfile && } +
+ Date: Sun, 31 Dec 2023 20:13:21 +0900 Subject: [PATCH 32/63] =?UTF-8?q?feat:=20Drawer=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=EC=97=90=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A5=BC=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 - 편집 버튼을 누를 시 Drawer가 나타납니다. - DrawerControlLabel을 통해 Drawer를 조작합니다. --- .../components/profile-edit-drawer/Drawer.tsx | 21 ++--- .../profile-edit-drawer/DrawerSide.tsx | 8 +- src/pages/Profile/index.tsx | 94 +++++++++++-------- 3 files changed, 72 insertions(+), 51 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index 4f4c8c6..c97549b 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -10,13 +10,13 @@ const DrawerContent = styled.div` ${tw`flex flex-col items-center justify-center`} ` -function Drawer() { - const [isOpen, setIsOpen] = useState(false) - - const handleToggleDrawer = () => { - setIsOpen(!isOpen) - } +interface DrawerProps { + children: React.ReactNode + isOpen: boolean + onToggle: () => void +} +function Drawer({ children, isOpen, onToggle }: DrawerProps) { return ( - - {/* Page content here -> Profile Page */} - Open - - + {children} + ) } diff --git a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx index 9eb3554..87d9395 100644 --- a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx @@ -22,11 +22,15 @@ const DetailSection = styled.div` ${tw`mx-auto w-10/12 flex flex-col justify-between items-center relative -mt-16`} ` -function DrawerSide() { +interface DrawerSideProps { + onToggle: () => void +} + +function DrawerSide({ onToggle }: DrawerSideProps) { return ( - {}} /> + diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 0013446..9299b26 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -5,6 +5,7 @@ import UserProfileImage from './components/profile/UserProfileImage' import UserProfileInfo from './components/profile/UserProfileInfo' import Header from './components/Header' import PostList from './components/profile/PostList' +import Drawer from './components/profile-edit-drawer/Drawer' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} @@ -35,11 +36,18 @@ const EditButton = styled.button` ${tw`w-6 h-6 self-end mb-3`} ` +const DrawerControlLabel = styled.label`` + function Profile() { const [userInfo, setUserInfo] = useState() const isMyProfile = userInfo?._id === import.meta.env.VITE_ADMIN_ID const [myInfo, setMyInfo] = useState(null) const [isFollowed, setIsFollowed] = useState(false) + const [isOpen, setIsOpen] = useState(false) + + const handleToggleDrawer = () => { + setIsOpen(!isOpen) + } useEffect(() => { const fetchUserInfo = async () => { @@ -70,46 +78,58 @@ function Profile() { } return ( - -
- - - -
-
- + +
+ + + +
+
+ + {isMyProfile && ( + + + + )} +
+ - {isMyProfile && } -
- - + + + + + -
-
- - - - - -
- + + + + ) } From 93ea538f518415f6802bb55f0b0b1fd341c5c54b Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 21:00:52 +0900 Subject: [PATCH 33/63] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A0=95=EB=B3=B4=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - zustand persist를 사용하여, localStorage에 사용자 정보를 저장한다. --- src/pages/Profile/index.tsx | 28 +++++++++++++++------------- src/stores/userProfileStore.ts | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 src/stores/userProfileStore.ts diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 9299b26..279265b 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -6,6 +6,7 @@ import UserProfileInfo from './components/profile/UserProfileInfo' import Header from './components/Header' import PostList from './components/profile/PostList' import Drawer from './components/profile-edit-drawer/Drawer' +import { useProfileStore } from '@/stores/userProfileStore' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} @@ -39,8 +40,8 @@ const EditButton = styled.button` const DrawerControlLabel = styled.label`` function Profile() { - const [userInfo, setUserInfo] = useState() - const isMyProfile = userInfo?._id === import.meta.env.VITE_ADMIN_ID + const { profile, setProfile } = useProfileStore() + const [isMyProfile, setIsMyProfile] = useState(false) const [myInfo, setMyInfo] = useState(null) const [isFollowed, setIsFollowed] = useState(false) const [isOpen, setIsOpen] = useState(false) @@ -52,7 +53,8 @@ function Profile() { useEffect(() => { const fetchUserInfo = async () => { const data = await getProfile(import.meta.env.VITE_ADMIN_ID) - setUserInfo(data) + setProfile(data) + setIsMyProfile(profile?._id === import.meta.env.VITE_ADMIN_ID) } fetchUserInfo() @@ -61,7 +63,7 @@ function Profile() { setMyInfo(data) } fetchMyProfile() - }, []) + }, [profile?._id, setProfile]) useEffect(() => { const checkIsFollowedUser = () => { @@ -84,12 +86,12 @@ function Profile() {
- +
{isMyProfile && ( @@ -104,12 +106,12 @@ function Profile() { )}
diff --git a/src/stores/userProfileStore.ts b/src/stores/userProfileStore.ts new file mode 100644 index 0000000..fb86a18 --- /dev/null +++ b/src/stores/userProfileStore.ts @@ -0,0 +1,22 @@ +import { create } from 'zustand' +import { persist, createJSONStorage } from 'zustand/middleware' + +type State = { + profile: User | null + setProfile: (user: User) => void +} + +export const useProfileStore = create()( + persist( + (set) => ({ + profile: null, + setProfile: (user: User) => { + set({ profile: user }) + } + }), + { + name: 'profile-storage', + storage: createJSONStorage(() => localStorage) + } + ) +) From 4776f22548aa417a879caa14c83195a27021b95b Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Sun, 31 Dec 2023 21:38:13 +0900 Subject: [PATCH 34/63] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84,=20?= =?UTF-8?q?=EC=BB=A4=EB=B2=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 변경된 이미지는 zustand를 통해 관리되는 사용자 정보를 통해 가져옵니다.(미리보기 형태) --- .../profile-edit-drawer/CoverImage.tsx | 12 ++-- .../profile-edit-drawer/ProfileImage.tsx | 12 +++- .../profile-edit-drawer/UploadImageButton.tsx | 66 +++++++++++++++++++ 3 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx diff --git a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx index ad4e94a..5238702 100644 --- a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx @@ -1,21 +1,25 @@ import tw, { styled } from 'twin.macro' import EditIcon from '../EditIcon' +import { useProfileStore } from '@/stores/userProfileStore' +import UploadImageButton from './UploadImageButton' const CoverImageWrapper = styled.div` ${tw`relative`} ` function CoverImage() { + const { profile } = useProfileStore() + return ( profile - + + + ) } diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx index f43ac93..aeff4c4 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx @@ -1,21 +1,27 @@ import tw, { styled } from 'twin.macro' import EditIcon from '../EditIcon' +import { useProfileStore } from '@/stores/userProfileStore' +import UploadImageButton from './UploadImageButton' const ProfileImageWrapper = styled.div` ${tw`relative overflow-hidden rounded-full`} ` function ProfileImage() { + const { profile } = useProfileStore() + return ( profile - + ) } diff --git a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx new file mode 100644 index 0000000..d6c6971 --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx @@ -0,0 +1,66 @@ +import { ChangeEvent, useCallback, useRef } from 'react' +import tw, { styled } from 'twin.macro' +import handleImageFormData from '@/utils/handleImageFormData' +import uploadImage from '@/apis/uploadImage' +import { useProfileStore } from '@/stores/userProfileStore' + +const FileInput = styled.input` + ${tw`file-input file-input-bordered w-full max-w-xs hidden`} +` +const UploadButton = styled.button`` + +interface UploadImageButtonProps { + children: React.ReactNode + className: string + isCover: boolean +} + +function UploadImageButton({ + children, + className, + isCover +}: UploadImageButtonProps) { + const inputRef = useRef(null) + const { setProfile } = useProfileStore() + + const handleUploadImage = useCallback( + async (e: ChangeEvent) => { + if (!e.target.files) return + const file = e.target.files[0] + const formData = handleImageFormData({ + imageFile: file, + type: 'Profile', + isCover + }) + + const response = await uploadImage(formData) + setProfile(response) + }, + [isCover, setProfile] + ) + + const handleClickUploadButton = useCallback(() => { + if (!inputRef.current) return + + inputRef.current.click() + }, []) + + return ( + <> + {/* Input은 display: none을 주어도, UploadButton에 의해 정상적으로 동작합니다. */} + handleUploadImage(e)} + /> + + {children} + + + ) +} + +export default UploadImageButton From c4f90db07893f50bac1195378d0bce860b51c830 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 09:50:30 +0900 Subject: [PATCH 35/63] =?UTF-8?q?modify:=20=EC=B4=88=EA=B8=B0=EA=B0=92?= =?UTF-8?q?=EC=9D=84=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=90=9C=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=EC=9D=98=20=EC=A0=95=EB=B3=B4=EB=A1=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/profile-edit-drawer/ProfileInputForm.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx index 9df5ab0..6e7a26d 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react' import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' +import { useProfileStore } from '@/stores/userProfileStore' const Form = styled.form` ${tw`w-full mb-36 flex flex-col gap-3`} @@ -14,8 +15,9 @@ const SubmitButton = styled.button` ` function ProfileInputForm() { - const [userName, setUserName] = useState('') - const [fullName, setFullName] = useState('') + const { profile } = useProfileStore() + const [userName, setUserName] = useState(profile?.username ?? '') + const [fullName, setFullName] = useState(profile?.fullName ?? '') const [password, setPassword] = useState('') const handleChangeUserName = (e: React.ChangeEvent) => { @@ -32,7 +34,7 @@ function ProfileInputForm() { const handleSubmit = (e: React.FormEvent) => { e.preventDefault() } - + return (
Date: Mon, 1 Jan 2024 09:59:43 +0900 Subject: [PATCH 36/63] =?UTF-8?q?modify:=20User=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - username 필드를 추가했습니다. --- src/types/type.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/type.d.ts b/src/types/type.d.ts index 99bb53b..be58bf2 100644 --- a/src/types/type.d.ts +++ b/src/types/type.d.ts @@ -17,6 +17,7 @@ interface User { email: string createdAt: string updatedAt: string + username?: string } interface Channel { From f48b21e2bd37266908743d72898d7ce80c4b9389 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 10:32:49 +0900 Subject: [PATCH 37/63] =?UTF-8?q?style:=20SubmitButton=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/profile-edit-drawer/ProfileInputForm.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx index 6e7a26d..4f21e50 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx @@ -4,14 +4,17 @@ import ProfileInput from './ProfileInput' import { useProfileStore } from '@/stores/userProfileStore' const Form = styled.form` - ${tw`w-full mb-36 flex flex-col gap-3`} + ${tw`w-full mb-36 flex flex-col`} ` const SubmitButton = styled.button` - padding: 10px 20px; + padding: 8px 15px; border-radius: 30px; background: #fff; box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1); + margin-top: 20px; + align-self: flex-end; + font-size: 0.8rem; ` function ProfileInputForm() { @@ -54,7 +57,7 @@ function ProfileInputForm() { From f1a38e771bdbb2901865ea5fb8eba7a2550da0ba Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 10:39:38 +0900 Subject: [PATCH 38/63] =?UTF-8?q?refactor:=20Form=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사용자명, 실명 변경 Form 컴포넌트와 비밀번호 변경 Form 컴포넌트를 분리했습니다. --- .../profile-edit-drawer/DrawerSide.tsx | 6 ++- ...ofileInputForm.tsx => ProfileNameForm.tsx} | 18 ++------ .../ProfilePasswordForm.tsx | 43 +++++++++++++++++++ 3 files changed, 50 insertions(+), 17 deletions(-) rename src/pages/Profile/components/profile-edit-drawer/{ProfileInputForm.tsx => ProfileNameForm.tsx} (73%) create mode 100644 src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx diff --git a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx index 87d9395..036c06a 100644 --- a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx @@ -1,7 +1,8 @@ import tw, { styled } from 'twin.macro' import CoverImage from './CoverImage' import ProfileImage from './ProfileImage' -import ProfileInputForm from './ProfileInputForm' +import ProfileNameForm from './ProfileNameForm' +import ProfilePasswordForm from './ProfilePasswordForm' const ProfileDrawerSide = styled.div`` @@ -36,7 +37,8 @@ function DrawerSide({ onToggle }: DrawerSideProps) { - + + diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx similarity index 73% rename from src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx rename to src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 4f21e50..3bd262f 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileInputForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -17,11 +17,10 @@ const SubmitButton = styled.button` font-size: 0.8rem; ` -function ProfileInputForm() { +function ProfileNameForm() { const { profile } = useProfileStore() const [userName, setUserName] = useState(profile?.username ?? '') const [fullName, setFullName] = useState(profile?.fullName ?? '') - const [password, setPassword] = useState('') const handleChangeUserName = (e: React.ChangeEvent) => { setUserName(e.target.value) @@ -30,10 +29,6 @@ function ProfileInputForm() { setFullName(e.target.value) } - const handleChangePassword = (e: React.ChangeEvent) => { - setPassword(e.target.value) - } - const handleSubmit = (e: React.FormEvent) => { e.preventDefault() } @@ -54,16 +49,9 @@ function ProfileInputForm() { type="text" onChangeInput={handleChangeFullName} /> - - 수정하기 + 변경 ) } -export default ProfileInputForm +export default ProfileNameForm diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx new file mode 100644 index 0000000..82945bb --- /dev/null +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -0,0 +1,43 @@ +import React, { useState } from 'react' +import ProfileInput from './ProfileInput' +import tw, { styled } from 'twin.macro' + +const Form = styled.form` + ${tw`w-full mb-36 flex flex-col`} +` + +const SubmitButton = styled.button` + padding: 8px 15px; + border-radius: 30px; + background: #fff; + box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1); + margin-top: 20px; + align-self: flex-end; + font-size: 0.8rem; +` +function ProfilePasswordForm() { + const [password, setPassword] = useState('') + + const handleChangePassword = (e: React.ChangeEvent) => { + setPassword(e.target.value) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + } + + return ( +
+ + 수정하기 + + ) +} + +export default ProfilePasswordForm From be71999a6e8905a663bf66e3c9d44191a998e64f Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 10:41:21 +0900 Subject: [PATCH 39/63] =?UTF-8?q?style:=20Form=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Profile/components/profile-edit-drawer/ProfileNameForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 3bd262f..44418a9 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -4,7 +4,7 @@ import ProfileInput from './ProfileInput' import { useProfileStore } from '@/stores/userProfileStore' const Form = styled.form` - ${tw`w-full mb-36 flex flex-col`} + ${tw`w-full flex flex-col`} ` const SubmitButton = styled.button` From 232eb5e2b18ed83b176239169c9afb28a395fa2e Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 10:56:30 +0900 Subject: [PATCH 40/63] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9D=BC=EC=B9=98=20=EC=97=AC=EB=B6=80=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProfilePasswordForm.tsx | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 82945bb..8b69242 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -3,7 +3,7 @@ import ProfileInput from './ProfileInput' import tw, { styled } from 'twin.macro' const Form = styled.form` - ${tw`w-full mb-36 flex flex-col`} + ${tw`w-full flex flex-col`} ` const SubmitButton = styled.button` @@ -17,15 +17,25 @@ const SubmitButton = styled.button` ` function ProfilePasswordForm() { const [password, setPassword] = useState('') + const [confirmPassword, setConfirmPassword] = useState('') + const [isPasswordMatch, setIsPasswordMatch] = useState(true) const handleChangePassword = (e: React.ChangeEvent) => { setPassword(e.target.value) } + const handleChangeConfirmPassword = ( + e: React.ChangeEvent + ) => { + const { value } = e.target + setConfirmPassword(value) + setIsPasswordMatch(password === value) + } + const handleSubmit = (e: React.FormEvent) => { e.preventDefault() } - + return (
- 수정하기 + + {!isPasswordMatch && ( + + 비밀번호가 일치하지 않습니다. + + )} + 변경 ) } From 210c2dd41bcff8e278eceac39939687d7e7a7a3f Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:16:08 +0900 Subject: [PATCH 41/63] =?UTF-8?q?modify:=20name=20props=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 - useForm을 사용하기 위해 input에 name을 추가했습니다. --- .../Profile/components/profile-edit-drawer/ProfileInput.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx index 46538c3..f7607d3 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx @@ -3,6 +3,7 @@ import tw, { styled } from 'twin.macro' interface InputProps { labelName: string + name: string value: string placeholder: string type: string @@ -19,6 +20,7 @@ const Label = styled.label` function ProfileInput({ labelName, + name, value, placeholder, type, @@ -29,6 +31,7 @@ function ProfileInput({ Date: Mon, 1 Jan 2024 11:20:42 +0900 Subject: [PATCH 42/63] =?UTF-8?q?feat:=20useForm=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 form을 처리하는 로직을 커스텀 훅으로 분리했습니다. --- src/hooks/useForm.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/hooks/useForm.ts diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts new file mode 100644 index 0000000..ca303cf --- /dev/null +++ b/src/hooks/useForm.ts @@ -0,0 +1,44 @@ +import { useState } from 'react' + +type Value = Record + +interface IUseForm { + initialValue: Value + onSubmit: (values: Value) => Promise + validate?: (values: Value) => any +} + +const useForm = ({ initialValue, onSubmit, validate }: IUseForm) => { + const [values, setValues] = useState(initialValue) + const [errors, setErrors] = useState({}) + const [isLoading, setIsLoading] = useState(false) + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target + setValues({ ...values, [name]: value }) + console.log(values) + } + + const handleSubmit = async (e: React.FormEvent) => { + setIsLoading(true) + e.preventDefault() + + const newErros = validate ? validate(values) : {} + if (Object.keys(newErros).length === 0) { + console.log('submit') + await onSubmit(values) + } + setErrors(newErros) + setIsLoading(false) + } + + return { + values, + errors, + isLoading, + handleChange, + handleSubmit + } +} + +export default useForm From d58982abf0e2c81cb1d0b50a432094b0af888892 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:21:15 +0900 Subject: [PATCH 43/63] =?UTF-8?q?refactor:=20form=EC=9D=84=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=9D=84=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 동일한 로직을 갖는 다른 form을 커스텀 훅으로 처리합니다. --- .../profile-edit-drawer/ProfileNameForm.tsx | 36 ++++++------ .../ProfilePasswordForm.tsx | 55 ++++++++++--------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 44418a9..aeb15bd 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' import { useProfileStore } from '@/stores/userProfileStore' +import useForm from '@/hooks/useForm' const Form = styled.form` ${tw`w-full flex flex-col`} @@ -19,37 +20,36 @@ const SubmitButton = styled.button` function ProfileNameForm() { const { profile } = useProfileStore() - const [userName, setUserName] = useState(profile?.username ?? '') - const [fullName, setFullName] = useState(profile?.fullName ?? '') - - const handleChangeUserName = (e: React.ChangeEvent) => { - setUserName(e.target.value) - } - const handleChangeFullName = (e: React.ChangeEvent) => { - setFullName(e.target.value) - } - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - } + const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ + initialValue: { + fullName: profile?.fullName || '', + userName: profile?.username || '' + }, + onSubmit: () => {}, + validate: () => {} + }) return (
- 변경 + + {isLoading ? '변경 중' : '변경'} + ) } diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 8b69242..2a08f29 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react' import ProfileInput from './ProfileInput' import tw, { styled } from 'twin.macro' +import useForm from '@/hooks/useForm' const Form = styled.form` ${tw`w-full flex flex-col`} @@ -16,47 +17,47 @@ const SubmitButton = styled.button` font-size: 0.8rem; ` function ProfilePasswordForm() { - const [password, setPassword] = useState('') - const [confirmPassword, setConfirmPassword] = useState('') - const [isPasswordMatch, setIsPasswordMatch] = useState(true) + const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ + initialValue: { + password: '', + confirmPassword: '' + }, + onSubmit: () => {}, + validate: ({ password, confirmPassword }) => { + const errors = { + confirmPassword: '' + } + if (password !== confirmPassword) { + errors.confirmPassword = '비밀번호가 일치하지 않습니다.' + } - const handleChangePassword = (e: React.ChangeEvent) => { - setPassword(e.target.value) - } - - const handleChangeConfirmPassword = ( - e: React.ChangeEvent - ) => { - const { value } = e.target - setConfirmPassword(value) - setIsPasswordMatch(password === value) - } - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - } + return errors + } + }) + console.log(errors) return (
- {!isPasswordMatch && ( - - 비밀번호가 일치하지 않습니다. - - )} + + {values.password !== values.confirmPassword && + '비밀번호가 일치하지 않습니다.'} + 변경 ) From 92fb4b89a90934515486ba78d865463a69b73d04 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:33:17 +0900 Subject: [PATCH 44/63] =?UTF-8?q?modify:=20interface=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useForm.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index ca303cf..1016c97 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -1,6 +1,8 @@ import { useState } from 'react' -type Value = Record +interface Value { + [key: string]: string +} interface IUseForm { initialValue: Value From 747a306440c33d32dc3422ed79ebdb60e7a0161a Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:35:20 +0900 Subject: [PATCH 45/63] =?UTF-8?q?feat:=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=90=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - zustand persist를 사용하여, 업데이트된 사용자 정보를 저장합니다. --- .../profile-edit-drawer/ProfileNameForm.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index aeb15bd..53f82b9 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -3,6 +3,7 @@ import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' import { useProfileStore } from '@/stores/userProfileStore' import useForm from '@/hooks/useForm' +import updateName from '@/apis/updateName' const Form = styled.form` ${tw`w-full flex flex-col`} @@ -19,22 +20,24 @@ const SubmitButton = styled.button` ` function ProfileNameForm() { - const { profile } = useProfileStore() - const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ + const { profile, setProfile } = useProfileStore() + const { values, isLoading, handleChange, handleSubmit } = useForm({ initialValue: { fullName: profile?.fullName || '', - userName: profile?.username || '' + username: profile?.username || '' }, - onSubmit: () => {}, - validate: () => {} + onSubmit: async (values) => { + const data = await updateName(values) + setProfile(data) + } }) return (
Date: Mon, 1 Jan 2024 11:35:52 +0900 Subject: [PATCH 46/63] =?UTF-8?q?feat:=20(=EC=9E=84=EC=8B=9C)=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?API=20=EC=9A=94=EC=B2=AD=20=ED=95=A8=EC=88=98=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/apis/updateName.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/apis/updateName.ts diff --git a/src/apis/updateName.ts b/src/apis/updateName.ts new file mode 100644 index 0000000..22f6d15 --- /dev/null +++ b/src/apis/updateName.ts @@ -0,0 +1,24 @@ +import { UPDATE_MY_PROFILE_PATH } from '@/utils/api_paths' +import axiosInstance from './api' + +interface Data { + [key: string]: string +} + +interface UpdateResponse extends User {} + +async function updateName(data: Data): Promise { + try { + const response = await axiosInstance.put(UPDATE_MY_PROFILE_PATH, data, { + headers: { + Authorization: `Bearer ${import.meta.env.VITE_TOKEN}` + } + }) + + return response.data + } catch (error) { + throw new Error('Error while fetching profile') + } +} + +export default updateName From 902505852dd2c01fee2cc00f4d6d7593c27361d2 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:47:51 +0900 Subject: [PATCH 47/63] =?UTF-8?q?modify:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20validate=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProfilePasswordForm.tsx | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 2a08f29..52206e4 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -1,7 +1,7 @@ -import React, { useState } from 'react' import ProfileInput from './ProfileInput' import tw, { styled } from 'twin.macro' import useForm from '@/hooks/useForm' +import updatePassword from '@/apis/updatePassword' const Form = styled.form` ${tw`w-full flex flex-col`} @@ -17,25 +17,18 @@ const SubmitButton = styled.button` font-size: 0.8rem; ` function ProfilePasswordForm() { - const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ + const { values, isLoading, handleChange, handleSubmit } = useForm({ initialValue: { password: '', confirmPassword: '' }, - onSubmit: () => {}, - validate: ({ password, confirmPassword }) => { - const errors = { - confirmPassword: '' - } - if (password !== confirmPassword) { - errors.confirmPassword = '비밀번호가 일치하지 않습니다.' - } - - return errors - } + onSubmit: async (values) => { + await updatePassword({ + password: values.password + }) + }, }) - console.log(errors) return ( - 변경 + + {isLoading ? '변경 중' : '변경'} + ) } From 36d5b3dddd3c517013bf29f90227267b3e1cd103 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 11:48:18 +0900 Subject: [PATCH 48/63] =?UTF-8?q?feat:=20(=EC=9E=84=EC=8B=9C)=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=ED=8C=A8=EC=8A=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20API=20=EC=9A=94=EC=B2=AD=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/updatePassword.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/apis/updatePassword.ts diff --git a/src/apis/updatePassword.ts b/src/apis/updatePassword.ts new file mode 100644 index 0000000..f4153ad --- /dev/null +++ b/src/apis/updatePassword.ts @@ -0,0 +1,24 @@ +import { UPDATE_MY_PASSWORD_PATH } from '@/utils/api_paths' +import axiosInstance from './api' + +interface Data { + [key: string]: string +} + +interface UpdateResponse extends User {} + +async function updatePassword(data: Data): Promise { + try { + const response = await axiosInstance.put(UPDATE_MY_PASSWORD_PATH, data, { + headers: { + Authorization: `Bearer ${import.meta.env.VITE_TOKEN}` + } + }) + + return response.data + } catch (error) { + throw new Error('Error while fetching profile') + } +} + +export default updatePassword From a6abe88354a3d3af9f3f80331ba51e1b3d9df0c7 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 12:26:01 +0900 Subject: [PATCH 49/63] =?UTF-8?q?build:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/components/profile-edit-drawer/Drawer.tsx | 1 - .../Profile/components/profile-edit-drawer/ProfileNameForm.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index c97549b..bbea5a3 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -1,5 +1,4 @@ import tw, { styled } from 'twin.macro' -import { useState } from 'react' import DrawerSide from './DrawerSide' const DrawerContainer = styled.div`` diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 53f82b9..66ee900 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -1,4 +1,3 @@ -import React, { useState } from 'react' import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' import { useProfileStore } from '@/stores/userProfileStore' From 9e0f4f42ba1d8ce1021bc0f567d67682d4cb1e70 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 12:26:18 +0900 Subject: [PATCH 50/63] =?UTF-8?q?modify:=20=EC=BD=98=EC=86=94=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useForm.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index 1016c97..06ef114 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -18,16 +18,13 @@ const useForm = ({ initialValue, onSubmit, validate }: IUseForm) => { const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target setValues({ ...values, [name]: value }) - console.log(values) } const handleSubmit = async (e: React.FormEvent) => { setIsLoading(true) e.preventDefault() - const newErros = validate ? validate(values) : {} if (Object.keys(newErros).length === 0) { - console.log('submit') await onSubmit(values) } setErrors(newErros) From fdda0d5204b5f106e11a68d8064ab9057228bfb3 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 12:28:29 +0900 Subject: [PATCH 51/63] =?UTF-8?q?modify:=20zustand=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사용자 프로필 정보를 기존 state에서 zustand로 관리하도록 변경했습니다. --- src/pages/Profile/index.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 279265b..8843392 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -42,7 +42,7 @@ const DrawerControlLabel = styled.label`` function Profile() { const { profile, setProfile } = useProfileStore() const [isMyProfile, setIsMyProfile] = useState(false) - const [myInfo, setMyInfo] = useState(null) + const [userInfo, setUserInfo] = useState(null) const [isFollowed, setIsFollowed] = useState(false) const [isOpen, setIsOpen] = useState(false) @@ -52,28 +52,28 @@ function Profile() { useEffect(() => { const fetchUserInfo = async () => { - const data = await getProfile(import.meta.env.VITE_ADMIN_ID) - setProfile(data) - setIsMyProfile(profile?._id === import.meta.env.VITE_ADMIN_ID) + const data = await getProfile(import.meta.env.VITE_USER_ID) + setUserInfo(data) } fetchUserInfo() const fetchMyProfile = async () => { - const data = await getProfile(import.meta.env.VITE_ADMIN_ID) - setMyInfo(data) + const data = await getProfile(import.meta.env.VITE_USER_ID) + setProfile(data) + setIsMyProfile(profile?._id === import.meta.env.VITE_USER_ID) } fetchMyProfile() }, [profile?._id, setProfile]) useEffect(() => { const checkIsFollowedUser = () => { - const res = myInfo?.following.some( - (item) => item.user === import.meta.env.VITE_ADMIN_ID + const res = profile?.following.some( + (item) => item.user === import.meta.env.VITE_USER_ID ) setIsFollowed(res!) } checkIsFollowedUser() - }, [myInfo]) + }, [profile?.following]) const handleClickFollowButton = () => { setIsFollowed((prev) => !prev) @@ -107,7 +107,7 @@ function Profile() { Date: Mon, 1 Jan 2024 13:12:10 +0900 Subject: [PATCH 52/63] =?UTF-8?q?comment:=20=EC=A3=BC=EC=84=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/components/EditIcon.tsx | 1 - src/pages/Profile/components/profile/FollowButton.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pages/Profile/components/EditIcon.tsx b/src/pages/Profile/components/EditIcon.tsx index cdcc138..09441a3 100644 --- a/src/pages/Profile/components/EditIcon.tsx +++ b/src/pages/Profile/components/EditIcon.tsx @@ -1,4 +1,3 @@ -// icon:edit | Feathericons https://feathericons.com/ | Cole Bemis import * as React from 'react' function EditIcon(props: React.SVGProps) { diff --git a/src/pages/Profile/components/profile/FollowButton.tsx b/src/pages/Profile/components/profile/FollowButton.tsx index a80e6f0..c5a23fc 100644 --- a/src/pages/Profile/components/profile/FollowButton.tsx +++ b/src/pages/Profile/components/profile/FollowButton.tsx @@ -1,4 +1,3 @@ -// icon:heart | Feathericons https://feathericons.com/ | Cole Bemis import * as React from 'react' function FollowButton(props: React.SVGProps) { From a2e87c28d04843edec7e742d44ab7c8cb0ecc115 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 13:15:13 +0900 Subject: [PATCH 53/63] =?UTF-8?q?refactor:=20import=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컨벤션에 따라 import 순서를 수정했습니다. --- .../Profile/components/profile-edit-drawer/CoverImage.tsx | 4 +++- .../Profile/components/profile-edit-drawer/ProfileImage.tsx | 4 +++- .../components/profile-edit-drawer/ProfileNameForm.tsx | 4 +++- .../components/profile-edit-drawer/ProfilePasswordForm.tsx | 6 ++++-- .../components/profile-edit-drawer/UploadImageButton.tsx | 2 ++ src/pages/Profile/index.tsx | 4 +++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx index 5238702..fb50acf 100644 --- a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx @@ -1,8 +1,10 @@ import tw, { styled } from 'twin.macro' + import EditIcon from '../EditIcon' -import { useProfileStore } from '@/stores/userProfileStore' import UploadImageButton from './UploadImageButton' +import { useProfileStore } from '@/stores/userProfileStore' + const CoverImageWrapper = styled.div` ${tw`relative`} ` diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx index aeff4c4..ec9f661 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx @@ -1,8 +1,10 @@ import tw, { styled } from 'twin.macro' + import EditIcon from '../EditIcon' -import { useProfileStore } from '@/stores/userProfileStore' import UploadImageButton from './UploadImageButton' +import { useProfileStore } from '@/stores/userProfileStore' + const ProfileImageWrapper = styled.div` ${tw`relative overflow-hidden rounded-full`} ` diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 66ee900..67f0e8f 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -1,8 +1,10 @@ import tw, { styled } from 'twin.macro' + import ProfileInput from './ProfileInput' + +import updateName from '@/apis/updateName' import { useProfileStore } from '@/stores/userProfileStore' import useForm from '@/hooks/useForm' -import updateName from '@/apis/updateName' const Form = styled.form` ${tw`w-full flex flex-col`} diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 52206e4..8da3f88 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -1,7 +1,9 @@ -import ProfileInput from './ProfileInput' import tw, { styled } from 'twin.macro' -import useForm from '@/hooks/useForm' + +import ProfileInput from './ProfileInput' + import updatePassword from '@/apis/updatePassword' +import useForm from '@/hooks/useForm' const Form = styled.form` ${tw`w-full flex flex-col`} diff --git a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx index d6c6971..3636b66 100644 --- a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx @@ -1,5 +1,7 @@ import { ChangeEvent, useCallback, useRef } from 'react' + import tw, { styled } from 'twin.macro' + import handleImageFormData from '@/utils/handleImageFormData' import uploadImage from '@/apis/uploadImage' import { useProfileStore } from '@/stores/userProfileStore' diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 8843392..b49ec55 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,11 +1,13 @@ -import getProfile from '@/apis/profile' import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' + import UserProfileImage from './components/profile/UserProfileImage' import UserProfileInfo from './components/profile/UserProfileInfo' import Header from './components/Header' import PostList from './components/profile/PostList' import Drawer from './components/profile-edit-drawer/Drawer' + +import getProfile from '@/apis/profile' import { useProfileStore } from '@/stores/userProfileStore' const ProfileContainer = styled.main` From 06e9e3176e20207b1abd720f7d316e73fdbe7f57 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 13:32:21 +0900 Subject: [PATCH 54/63] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 공통 컴포넌트(ProfileImage)로 분리함에 따라 사용하지 않습니다. --- .../components/profile/UserProfileImage.tsx | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/pages/Profile/components/profile/UserProfileImage.tsx diff --git a/src/pages/Profile/components/profile/UserProfileImage.tsx b/src/pages/Profile/components/profile/UserProfileImage.tsx deleted file mode 100644 index e99dac6..0000000 --- a/src/pages/Profile/components/profile/UserProfileImage.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import tw, { styled } from 'twin.macro' - -interface UserProfileImageProps { - imgSrc?: string - isMyProfile: boolean -} - -const UserProfileImageWrapper = styled.div`` - -const ProfileImage = styled.img` - ${tw`w-32 h-32 rounded-full object-cover z-10 bg-white`} -` - -function UserProfileImage({ imgSrc }: UserProfileImageProps) { - return ( - - - - ) -} - -export default UserProfileImage From 6bf79a6117dacfda8687aab53170769c470456ae Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 13:33:37 +0900 Subject: [PATCH 55/63] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=A4=91=EB=B3=B5=20=EC=B5=9C=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ProfileImage, CoverImage를 공통 컴포넌트로 분리했습니다. --- .../profile-edit-drawer/CoverImage.tsx | 13 ++++++------- .../profile-edit-drawer/DrawerSide.tsx | 18 ++++++++++++++++-- .../profile-edit-drawer/ProfileImage.tsx | 17 +++++++---------- src/pages/Profile/index.tsx | 14 ++++---------- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx index fb50acf..dc914ee 100644 --- a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx @@ -1,15 +1,16 @@ import tw, { styled } from 'twin.macro' -import EditIcon from '../EditIcon' -import UploadImageButton from './UploadImageButton' - import { useProfileStore } from '@/stores/userProfileStore' const CoverImageWrapper = styled.div` ${tw`relative`} ` -function CoverImage() { +interface CoverImageProps { + children?: React.ReactNode +} + +function CoverImage({ children }: CoverImageProps) { const { profile } = useProfileStore() return ( @@ -19,9 +20,7 @@ function CoverImage() { alt="profile" className="w-full h-64 object-cover p-0 rounded-none brightness-50" /> - - - + {children} ) } diff --git a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx index 036c06a..5d0a9ec 100644 --- a/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/DrawerSide.tsx @@ -3,6 +3,8 @@ import CoverImage from './CoverImage' import ProfileImage from './ProfileImage' import ProfileNameForm from './ProfileNameForm' import ProfilePasswordForm from './ProfilePasswordForm' +import UploadImageButton from './UploadImageButton' +import EditIcon from '../EditIcon' const ProfileDrawerSide = styled.div`` @@ -34,9 +36,21 @@ function DrawerSide({ onToggle }: DrawerSideProps) { - + + + + + - + + + + + diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx index ec9f661..a7cfd32 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx @@ -1,17 +1,18 @@ import tw, { styled } from 'twin.macro' -import EditIcon from '../EditIcon' -import UploadImageButton from './UploadImageButton' - import { useProfileStore } from '@/stores/userProfileStore' const ProfileImageWrapper = styled.div` ${tw`relative overflow-hidden rounded-full`} ` -function ProfileImage() { +interface ProfileImageProps { + children?: React.ReactNode +} + +function ProfileImage({ children }: ProfileImageProps) { const { profile } = useProfileStore() - + return ( profile - - - + {children} ) } diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index b49ec55..da91353 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from 'react' import tw, { styled } from 'twin.macro' -import UserProfileImage from './components/profile/UserProfileImage' import UserProfileInfo from './components/profile/UserProfileInfo' import Header from './components/Header' import PostList from './components/profile/PostList' @@ -9,6 +8,8 @@ import Drawer from './components/profile-edit-drawer/Drawer' import getProfile from '@/apis/profile' import { useProfileStore } from '@/stores/userProfileStore' +import ProfileImage from './components/profile-edit-drawer/ProfileImage' +import CoverImage from './components/profile-edit-drawer/CoverImage' const ProfileContainer = styled.main` ${tw`w-full h-screen relative`} @@ -18,10 +19,6 @@ const UserProfileSection = styled.section` ${tw`w-full h-full`} ` -const CoverImage = styled.img` - ${tw`w-full h-64 object-cover`} -` - const DetailSection = styled.div` ${tw`mx-auto w-10/12 flex justify-between items-center relative -mt-16`} ` @@ -88,14 +85,11 @@ function Profile() {
- +
- + {isMyProfile && ( Date: Mon, 1 Jan 2024 21:17:31 +0900 Subject: [PATCH 56/63] =?UTF-8?q?feat:=20DrawerContent=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20=EB=B6=84=EA=B8=B0=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 분기 처리가 없으면, DrawerSide와 겹쳐져서 이전 버튼이 동작하지 않았습니다. --- src/pages/Profile/components/profile-edit-drawer/Drawer.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index bbea5a3..962d568 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -25,7 +25,9 @@ function Drawer({ children, isOpen, onToggle }: DrawerProps) { checked={isOpen} onChange={onToggle} /> - {children} + {!isOpen && ( + {children} + )} ) From ec276c8fbbfb00baad4adc743541ae38c2f0c3bb Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 21:38:35 +0900 Subject: [PATCH 57/63] =?UTF-8?q?feat:=20=EB=A1=9C=EB=94=A9=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=B4=20sleep=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 변경이 된 후, 사용자가 페이지를 빠져나갈 수 있도록 합니다. --- .../components/profile-edit-drawer/ProfileNameForm.tsx | 5 +++++ .../profile-edit-drawer/ProfilePasswordForm.tsx | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 67f0e8f..acff176 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -20,6 +20,10 @@ const SubmitButton = styled.button` font-size: 0.8rem; ` +const sleep = () => { + return new Promise((resolve) => setTimeout(resolve, 1000)) +} + function ProfileNameForm() { const { profile, setProfile } = useProfileStore() const { values, isLoading, handleChange, handleSubmit } = useForm({ @@ -28,6 +32,7 @@ function ProfileNameForm() { username: profile?.username || '' }, onSubmit: async (values) => { + await sleep() const data = await updateName(values) setProfile(data) } diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 8da3f88..7f66602 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -18,13 +18,19 @@ const SubmitButton = styled.button` align-self: flex-end; font-size: 0.8rem; ` + +const sleep = () => { + return new Promise((resolve) => setTimeout(resolve, 1000)); +}; + function ProfilePasswordForm() { - const { values, isLoading, handleChange, handleSubmit } = useForm({ + const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ initialValue: { password: '', confirmPassword: '' }, onSubmit: async (values) => { + await sleep() await updatePassword({ password: values.password }) From 6a50c31bee9b08364012fba7c2a2a32ec7ab5d56 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Mon, 1 Jan 2024 21:39:03 +0900 Subject: [PATCH 58/63] =?UTF-8?q?modify:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EB=A5=BC=20=EC=9E=85=EB=A0=A5=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/profile-edit-drawer/ProfilePasswordForm.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 7f66602..fd2beef 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -56,7 +56,9 @@ function ProfilePasswordForm() { onChangeInput={handleChange} /> - {values.password !== values.confirmPassword && + {values.password.length === 0 && values.confirmPassword.length !== 0 && '비밀번호를 입력해주세요.'} + {values.password.length !== 0 && + values.password !== values.confirmPassword && '비밀번호가 일치하지 않습니다.'} From 4189cf4a9bbdcc83ceef8224baf8997c7577177e Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Tue, 2 Jan 2024 13:54:26 +0900 Subject: [PATCH 59/63] =?UTF-8?q?rename:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20API=20=EC=9A=94=EC=B2=AD=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=9D=98=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프로필 관련 API 요청 함수를 profile 폴더 내로 옮겼습니다. --- src/apis/{ => profile}/profile.ts | 6 ++---- src/apis/{ => profile}/updateName.ts | 0 src/apis/{ => profile}/updatePassword.ts | 0 src/apis/{ => profile}/uploadImage.ts | 0 src/pages/Profile/index.tsx | 2 +- 5 files changed, 3 insertions(+), 5 deletions(-) rename src/apis/{ => profile}/profile.ts (71%) rename src/apis/{ => profile}/updateName.ts (100%) rename src/apis/{ => profile}/updatePassword.ts (100%) rename src/apis/{ => profile}/uploadImage.ts (100%) diff --git a/src/apis/profile.ts b/src/apis/profile/profile.ts similarity index 71% rename from src/apis/profile.ts rename to src/apis/profile/profile.ts index 6fa6aca..a2a7de3 100644 --- a/src/apis/profile.ts +++ b/src/apis/profile/profile.ts @@ -1,13 +1,11 @@ import { GET_USER_PROFILE_PATH } from '@/utils/api_paths' -import axiosInstance from './api' +import axiosInstance from '../api' interface ProfileResponse extends User {} async function getProfile(id: string): Promise { try { - const response = await axiosInstance.get( - `${GET_USER_PROFILE_PATH}/${id}` - ) + const response = await axiosInstance.get(`${GET_USER_PROFILE_PATH}/${id}`) return response.data } catch (error) { diff --git a/src/apis/updateName.ts b/src/apis/profile/updateName.ts similarity index 100% rename from src/apis/updateName.ts rename to src/apis/profile/updateName.ts diff --git a/src/apis/updatePassword.ts b/src/apis/profile/updatePassword.ts similarity index 100% rename from src/apis/updatePassword.ts rename to src/apis/profile/updatePassword.ts diff --git a/src/apis/uploadImage.ts b/src/apis/profile/uploadImage.ts similarity index 100% rename from src/apis/uploadImage.ts rename to src/apis/profile/uploadImage.ts diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index da91353..adffad4 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -6,7 +6,7 @@ import Header from './components/Header' import PostList from './components/profile/PostList' import Drawer from './components/profile-edit-drawer/Drawer' -import getProfile from '@/apis/profile' +import getProfile from '@/apis/profile/profile' import { useProfileStore } from '@/stores/userProfileStore' import ProfileImage from './components/profile-edit-drawer/ProfileImage' import CoverImage from './components/profile-edit-drawer/CoverImage' From b26ef7bb8316e19fbc05f76a8400d0022e092e52 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Tue, 2 Jan 2024 13:56:51 +0900 Subject: [PATCH 60/63] =?UTF-8?q?style:=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 인라인으로 작성한 스타일을 tw-macro 방식으로 변경했습니다. --- .../components/profile-edit-drawer/Drawer.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index 962d568..ae2cbbe 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -1,12 +1,16 @@ import tw, { styled } from 'twin.macro' import DrawerSide from './DrawerSide' -const DrawerContainer = styled.div`` +const DrawerContainer = styled.div` + ${tw`drawer drawer-end`} +` -const DrawerControl = styled.input`` +const DrawerControl = styled.input` + ${tw`drawer-toggle`} +` const DrawerContent = styled.div` - ${tw`flex flex-col items-center justify-center`} + ${tw`flex flex-col items-center justify-center drawer-content`} ` interface DrawerProps { @@ -17,17 +21,14 @@ interface DrawerProps { function Drawer({ children, isOpen, onToggle }: DrawerProps) { return ( - + - {!isOpen && ( - {children} - )} + {!isOpen && {children}} ) From b1ec0e09b609fa4a27230ecfe50a42327b4d3aad Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Tue, 2 Jan 2024 21:16:40 +0900 Subject: [PATCH 61/63] =?UTF-8?q?fix:=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=9D=B4=EB=A6=84=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `Commnet`를 `Comment`로 수정 --- src/types/type.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/type.d.ts b/src/types/type.d.ts index be58bf2..88364e1 100644 --- a/src/types/type.d.ts +++ b/src/types/type.d.ts @@ -51,7 +51,7 @@ interface Like { updatedAt: string } -interface Commnet { +interface Comment { _id: string comment: string author: User From 89f8ee177870179647bfe009ad96d99596dc5461 Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Tue, 2 Jan 2024 21:38:53 +0900 Subject: [PATCH 62/63] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 화살표 함수로 통일성을 부여했습니다. --- src/pages/Profile/components/EditIcon.tsx | 2 +- src/pages/Profile/components/Header.tsx | 2 +- .../Profile/components/profile-edit-drawer/CoverImage.tsx | 2 +- src/pages/Profile/components/profile-edit-drawer/Drawer.tsx | 2 +- .../Profile/components/profile-edit-drawer/DrawerSide.tsx | 2 +- .../Profile/components/profile-edit-drawer/ProfileImage.tsx | 2 +- .../Profile/components/profile-edit-drawer/ProfileInput.tsx | 4 ++-- .../components/profile-edit-drawer/ProfileNameForm.tsx | 2 +- .../components/profile-edit-drawer/ProfilePasswordForm.tsx | 2 +- .../components/profile-edit-drawer/UploadImageButton.tsx | 4 ++-- src/pages/Profile/components/profile/FollowButton.tsx | 2 +- src/pages/Profile/components/profile/PostList.tsx | 2 +- src/pages/Profile/components/profile/UserProfileInfo.tsx | 4 ++-- src/pages/Profile/index.tsx | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/pages/Profile/components/EditIcon.tsx b/src/pages/Profile/components/EditIcon.tsx index 09441a3..ad7f428 100644 --- a/src/pages/Profile/components/EditIcon.tsx +++ b/src/pages/Profile/components/EditIcon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -function EditIcon(props: React.SVGProps) { +const EditIcon = (props: React.SVGProps) => { return ( { return ( diff --git a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx index dc914ee..956cb30 100644 --- a/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/CoverImage.tsx @@ -10,7 +10,7 @@ interface CoverImageProps { children?: React.ReactNode } -function CoverImage({ children }: CoverImageProps) { +const CoverImage = ({ children }: CoverImageProps) => { const { profile } = useProfileStore() return ( diff --git a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx index ae2cbbe..da12094 100644 --- a/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/Drawer.tsx @@ -19,7 +19,7 @@ interface DrawerProps { onToggle: () => void } -function Drawer({ children, isOpen, onToggle }: DrawerProps) { +const Drawer = ({ children, isOpen, onToggle }: DrawerProps) => { return ( void } -function DrawerSide({ onToggle }: DrawerSideProps) { +const DrawerSide = ({ onToggle }: DrawerSideProps) => { return ( diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx index a7cfd32..77c98b1 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileImage.tsx @@ -10,7 +10,7 @@ interface ProfileImageProps { children?: React.ReactNode } -function ProfileImage({ children }: ProfileImageProps) { +const ProfileImage = ({ children }: ProfileImageProps) => { const { profile } = useProfileStore() return ( diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx index f7607d3..703df08 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileInput.tsx @@ -18,14 +18,14 @@ const Label = styled.label` ${tw`label`} ` -function ProfileInput({ +const ProfileInput = ({ labelName, name, value, placeholder, type, onChangeInput -}: InputProps) { +}: InputProps) => { return (
diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index acff176..2ee0fe3 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -24,7 +24,7 @@ const sleep = () => { return new Promise((resolve) => setTimeout(resolve, 1000)) } -function ProfileNameForm() { +const ProfileNameForm = () => { const { profile, setProfile } = useProfileStore() const { values, isLoading, handleChange, handleSubmit } = useForm({ initialValue: { diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index fd2beef..1009dcb 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -23,7 +23,7 @@ const sleep = () => { return new Promise((resolve) => setTimeout(resolve, 1000)); }; -function ProfilePasswordForm() { +const ProfilePasswordForm = () => { const { values, errors, isLoading, handleChange, handleSubmit } = useForm({ initialValue: { password: '', diff --git a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx index 3636b66..b6891dc 100644 --- a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx @@ -17,11 +17,11 @@ interface UploadImageButtonProps { isCover: boolean } -function UploadImageButton({ +const UploadImageButton = ({ children, className, isCover -}: UploadImageButtonProps) { +}: UploadImageButtonProps) => { const inputRef = useRef(null) const { setProfile } = useProfileStore() diff --git a/src/pages/Profile/components/profile/FollowButton.tsx b/src/pages/Profile/components/profile/FollowButton.tsx index c5a23fc..8f61ce3 100644 --- a/src/pages/Profile/components/profile/FollowButton.tsx +++ b/src/pages/Profile/components/profile/FollowButton.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -function FollowButton(props: React.SVGProps) { +const FollowButton = (props: React.SVGProps) => { return ( { return ( {listTitle} diff --git a/src/pages/Profile/components/profile/UserProfileInfo.tsx b/src/pages/Profile/components/profile/UserProfileInfo.tsx index d52b606..aee8097 100644 --- a/src/pages/Profile/components/profile/UserProfileInfo.tsx +++ b/src/pages/Profile/components/profile/UserProfileInfo.tsx @@ -36,7 +36,7 @@ const ChatButton = styled.button` ${tw`w-6 h-6`} ` -function UserProfileInfo({ +const UserProfileInfo = ({ fullName, userName, email, @@ -46,7 +46,7 @@ function UserProfileInfo({ isMyProfile, isFollowed, onClickFollowButton -}: UserProfileInfoProps) { +}: UserProfileInfoProps) => { return ( diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index adffad4..519b747 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -38,7 +38,7 @@ const EditButton = styled.button` const DrawerControlLabel = styled.label`` -function Profile() { +const Profile = () => { const { profile, setProfile } = useProfileStore() const [isMyProfile, setIsMyProfile] = useState(false) const [userInfo, setUserInfo] = useState(null) From 8e6aa7f2a7b9acbcc1b85dac5a5d7201ca42becb Mon Sep 17 00:00:00 2001 From: lunarmoon7 <49crehbgr@gmail.com> Date: Tue, 2 Jan 2024 21:39:56 +0900 Subject: [PATCH 63/63] =?UTF-8?q?refactor:=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20import=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/profile/updateName.ts | 2 +- src/apis/profile/updatePassword.ts | 2 +- src/apis/profile/uploadImage.ts | 2 +- .../Profile/components/profile-edit-drawer/ProfileNameForm.tsx | 2 +- .../components/profile-edit-drawer/ProfilePasswordForm.tsx | 2 +- .../components/profile-edit-drawer/UploadImageButton.tsx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/apis/profile/updateName.ts b/src/apis/profile/updateName.ts index 22f6d15..859f0fc 100644 --- a/src/apis/profile/updateName.ts +++ b/src/apis/profile/updateName.ts @@ -1,5 +1,5 @@ import { UPDATE_MY_PROFILE_PATH } from '@/utils/api_paths' -import axiosInstance from './api' +import axiosInstance from '../api' interface Data { [key: string]: string diff --git a/src/apis/profile/updatePassword.ts b/src/apis/profile/updatePassword.ts index f4153ad..e28bcd1 100644 --- a/src/apis/profile/updatePassword.ts +++ b/src/apis/profile/updatePassword.ts @@ -1,5 +1,5 @@ import { UPDATE_MY_PASSWORD_PATH } from '@/utils/api_paths' -import axiosInstance from './api' +import axiosInstance from '../api' interface Data { [key: string]: string diff --git a/src/apis/profile/uploadImage.ts b/src/apis/profile/uploadImage.ts index 618afb6..512d53c 100644 --- a/src/apis/profile/uploadImage.ts +++ b/src/apis/profile/uploadImage.ts @@ -1,5 +1,5 @@ import { UPDATE_PROFILE_IMAGE_PATH } from '@/utils/api_paths' -import axiosInstance from './api' +import axiosInstance from '../api' async function uploadImage(formData: FormData) { try { diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx index 2ee0fe3..b60864f 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfileNameForm.tsx @@ -2,7 +2,7 @@ import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' -import updateName from '@/apis/updateName' +import updateName from '@/apis/profile/updateName' import { useProfileStore } from '@/stores/userProfileStore' import useForm from '@/hooks/useForm' diff --git a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx index 1009dcb..7fd571d 100644 --- a/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/ProfilePasswordForm.tsx @@ -2,7 +2,7 @@ import tw, { styled } from 'twin.macro' import ProfileInput from './ProfileInput' -import updatePassword from '@/apis/updatePassword' +import updatePassword from '@/apis/profile/updatePassword' import useForm from '@/hooks/useForm' const Form = styled.form` diff --git a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx index b6891dc..5b5ae2d 100644 --- a/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx +++ b/src/pages/Profile/components/profile-edit-drawer/UploadImageButton.tsx @@ -3,7 +3,7 @@ import { ChangeEvent, useCallback, useRef } from 'react' import tw, { styled } from 'twin.macro' import handleImageFormData from '@/utils/handleImageFormData' -import uploadImage from '@/apis/uploadImage' +import uploadImage from '@/apis/profile/uploadImage' import { useProfileStore } from '@/stores/userProfileStore' const FileInput = styled.input`