From e503eaf3c998616d2f147c3b117fd9c699cb0dd6 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:03:12 +0900 Subject: [PATCH 01/31] =?UTF-8?q?Feat:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20ui=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/index.tsx | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/components/Skeleton/index.tsx diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx new file mode 100644 index 00000000..6280dc72 --- /dev/null +++ b/src/components/Skeleton/index.tsx @@ -0,0 +1,39 @@ +import { SkeletonContainer } from './styles'; + +interface SkeletonProps { + width?: string | number; + height?: string | number; + borderRadius?: string | number; + className?: string; + style?: React.CSSProperties; +} + +const Skeleton: React.FC = ({ + width = '100%', + height = '16px', + borderRadius = '4px', + className = '', + style = {}, +}) => { + // width와 height가 숫자인 경우 px 단위를 추가 + const getSize = (size: string | number) => { + if (typeof size === 'number') { + return `${size}px`; + } + return size; + }; + + return ( + + ); +}; + +export default Skeleton; From b0f218436bfa0e48fb4bc9b490b692a7b29c82fc Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:04:24 +0900 Subject: [PATCH 02/31] =?UTF-8?q?Feat:=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/styles.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/components/Skeleton/styles.tsx diff --git a/src/components/Skeleton/styles.tsx b/src/components/Skeleton/styles.tsx new file mode 100644 index 00000000..14638099 --- /dev/null +++ b/src/components/Skeleton/styles.tsx @@ -0,0 +1,19 @@ +import { styled } from 'styled-components'; + +export const SkeletonContainer = styled.div` + background-color: #e0e0e0; + position: relative; + overflow: hidden; + background: linear-gradient(90deg, #e0e0e0 0%, #f0f0f0 50%, #e0e0e0 100%); + background-size: 200% 100%; + animation: shimmer 1.5s infinite; + + @keyframes shimmer { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } + } +`; From f19e39445c579384bed771ac5081a2a867e6ba46 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:05:03 +0900 Subject: [PATCH 03/31] =?UTF-8?q?Refactor:=20=EB=A1=9C=EB=94=A9=EC=A4=91?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0=20=ED=9B=84=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20=EC=A0=81=EC=9A=A9(=ED=94=84=EB=A1=9C=ED=95=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/index.tsx | 75 +++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 4953104f..7a62c668 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -1,3 +1,4 @@ +import * as React from 'react'; import { useState, useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; @@ -19,9 +20,9 @@ import button_plus from '@assets/default/plus.svg'; import CommentBottomSheet from '@components/BottomSheet/CommentBottomSheet'; import OptionsBottomSheet from '@components/BottomSheet/OptionsBottomSheet'; import { OODDFrame } from '@components/Frame/Frame'; -import Loading from '@components/Loading'; import Modal from '@components/Modal'; import NavBar from '@components/NavBar'; +import Skeleton from '@components/Skeleton'; import { StyledText } from '@components/Text/StyledText'; import TopBar from '@components/TopBar'; @@ -69,15 +70,19 @@ const Profile: React.FC = () => { try { const response = await getUserInfoApi(profileUserId); const postResponse = await getUserPostListApi(1, 10, profileUserId); - setUserInfo(response.data); - setPosts(postResponse.data.post); - setTotalPosts(postResponse.data.totalPostsCount); + // 1초 동안 스켈레톤 보여주기 확인용! 나중에 다 수정하고 삭제예정! + setTimeout(() => { + setUserInfo(response.data); + setPosts(postResponse.data.post); + setTotalPosts(postResponse.data.totalPostsCount); + setIsLoading(false); + }, 1000); } catch (error) { console.error('데이터 가져오기 실패:', error); - } finally { - setIsLoading(false); + setIsLoading(false); // 실패해도 로딩 상태는 끝나야 하니까 여기서도 false 처리 } }; + fetchData(); }, [profileUserId]); @@ -103,7 +108,63 @@ const Profile: React.FC = () => { setIsModalOpen(true); }; - if (isLoading) return ; + // 로딩 중일 때 스켈레톤 UI 표시 + if (isLoading) { + return ( + + + {isMyPage ? ( + + ) : ( + navigate(-1)} + onClickRightButton={() => setIsOptionsBottomSheetOpen(true)} + /> + )} + +
+ {/* 프로필 섹션 스켈레톤 */} + +
+ + +
+
+ + {/* 버튼 스켈레톤 */} +
+ +
+ + {/* 통계 스켈레톤 */} + + + + + {isMyPage && ( + + + + )} + + + + + + {/* 포스트 스켈레톤 */} + + {[1, 2].map((item) => ( + + ))} + + + {isMyPage && } +
+
+ ); + } return ( From 7921a8aadeee3a7dded890b942faf21ff651e8a3 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:05:21 +0900 Subject: [PATCH 04/31] =?UTF-8?q?Fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=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/styles.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/Profile/styles.tsx b/src/pages/Profile/styles.tsx index 7db238d6..5e792ffa 100644 --- a/src/pages/Profile/styles.tsx +++ b/src/pages/Profile/styles.tsx @@ -35,7 +35,6 @@ export const Stat = styled.div` export const StatNumber = styled.div` color: ${({ theme }) => theme.colors.text.caption}; - //변경된 컬러시스템에서의 gray4가 800으로 나와있어서 적용해보면 색상이 다르게 나옵니다! text-align: center; font-family: 'Pretendard'; font-size: 1rem; From a09ee4da07b7df657dd7aae231345a08b033514f Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:05:37 +0900 Subject: [PATCH 05/31] =?UTF-8?q?Fix:=20=EB=B2=84=ED=8A=BC=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/ButtonSecondary/styles.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Profile/ButtonSecondary/styles.tsx b/src/pages/Profile/ButtonSecondary/styles.tsx index af4a1820..22682626 100644 --- a/src/pages/Profile/ButtonSecondary/styles.tsx +++ b/src/pages/Profile/ButtonSecondary/styles.tsx @@ -1,7 +1,7 @@ import { styled } from 'styled-components'; export const Button = styled.button` - width: 100%; + width: 90%; margin: 16px auto; height: 3.1rem; text-align: center; From 3ccc62de796dbb9acf8ad235230e180b7291d44e Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:30:46 +0900 Subject: [PATCH 06/31] =?UTF-8?q?Fix:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20=ED=8F=AC=EC=8A=A4=ED=8A=B8=204=EA=B0=9C=EB=A1=9C?= =?UTF-8?q?=20=EC=A6=9D=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 7a62c668..2406deba 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -155,8 +155,8 @@ const Profile: React.FC = () => { {/* 포스트 스켈레톤 */} - {[1, 2].map((item) => ( - + {[1, 2, 3, 4].map((item) => ( + ))} From ba8b981e781e65880d6f3379c292abba5ac265a2 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:31:28 +0900 Subject: [PATCH 07/31] =?UTF-8?q?Fix:=20ui=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/styles.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Profile/styles.tsx b/src/pages/Profile/styles.tsx index 5e792ffa..24a43903 100644 --- a/src/pages/Profile/styles.tsx +++ b/src/pages/Profile/styles.tsx @@ -59,6 +59,7 @@ export const PostsContainer = styled.div` gap: 15px; margin-bottom: 100px; padding: 20px; + width: 100%; `; export const AddButton = styled.button` From d9c742fad58cbfd230be3806706cce09538491b1 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:11:25 +0900 Subject: [PATCH 08/31] =?UTF-8?q?Fix:=20rem=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index 6280dc72..f4f5bea8 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -15,7 +15,7 @@ const Skeleton: React.FC = ({ className = '', style = {}, }) => { - // width와 height가 숫자인 경우 px 단위를 추가 + // width와 height가 숫자인 경우 rem 단위를 추가 const getSize = (size: string | number) => { if (typeof size === 'number') { return `${size}px`; From d74aaaa1cf126d038a35bc7c4d943d3611089315 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:11:35 +0900 Subject: [PATCH 09/31] =?UTF-8?q?FIx:=20=EC=8A=A4=ED=83=80=EC=9D=BC=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 --- src/pages/Profile/index.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 2406deba..5c086bb5 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -37,6 +37,7 @@ import UserProfile from './UserProfile/index'; import { ProfileContainer, Header, + ProfileDetail, StatsContainer, Stat, StatNumber, @@ -126,11 +127,12 @@ const Profile: React.FC = () => {
{/* 프로필 섹션 스켈레톤 */} - -
+ + + - -
+ +
{/* 버튼 스켈레톤 */} From 469d80c7b400446b621267f68b91373b6bc796b4 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:11:46 +0900 Subject: [PATCH 10/31] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=EC=8B=9C=ED=8A=B8=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/styles.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/Profile/styles.tsx b/src/pages/Profile/styles.tsx index 24a43903..6ce655e4 100644 --- a/src/pages/Profile/styles.tsx +++ b/src/pages/Profile/styles.tsx @@ -12,6 +12,14 @@ export const ProfileContainer = styled.div` padding-top: 0rem; `; +export const ProfileDetail = styled.div` + flex: 1; + margin-left: 15px; + display: flex; + flex-direction: column; + gap: 5px; +`; + export const Header = styled.div` margin: 8px 20px; display: flex; From bf74952ed6edeb451e3e2db83f3fd687062afb42 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:13:59 +0900 Subject: [PATCH 11/31] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index f4f5bea8..cfe5f9fc 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -13,7 +13,6 @@ const Skeleton: React.FC = ({ height = '16px', borderRadius = '4px', className = '', - style = {}, }) => { // width와 height가 숫자인 경우 rem 단위를 추가 const getSize = (size: string | number) => { @@ -30,7 +29,6 @@ const Skeleton: React.FC = ({ width: getSize(width), height: getSize(height), borderRadius: getSize(borderRadius), - ...style, }} /> ); From 25a87347f7cf85a01c1f4fb7f585fb685363ef56 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:16:45 +0900 Subject: [PATCH 12/31] =?UTF-8?q?Fix:=20=EB=B3=B4=EB=8D=94=20=EB=91=A5?= =?UTF-8?q?=EA=B8=80=EA=B2=8C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index cfe5f9fc..085694e5 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -11,7 +11,7 @@ interface SkeletonProps { const Skeleton: React.FC = ({ width = '100%', height = '16px', - borderRadius = '4px', + borderRadius = '5px', className = '', }) => { // width와 height가 숫자인 경우 rem 단위를 추가 From 236f5af3a810a735903b1ec26c50ec3d8f00d7e7 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:46:28 +0900 Subject: [PATCH 13/31] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=83=80=EC=9D=BC=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 --- src/pages/Profile/index.tsx | 7 ++++--- src/pages/Profile/styles.tsx | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 5c086bb5..4637742c 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -46,6 +46,7 @@ import { AddButton, NoPostWrapper, Button, + ButtonSkeleton, } from './styles'; const Profile: React.FC = () => { @@ -136,9 +137,9 @@ const Profile: React.FC = () => { {/* 버튼 스켈레톤 */} -
- -
+ + + {/* 통계 스켈레톤 */} diff --git a/src/pages/Profile/styles.tsx b/src/pages/Profile/styles.tsx index 6ce655e4..2aea662a 100644 --- a/src/pages/Profile/styles.tsx +++ b/src/pages/Profile/styles.tsx @@ -102,3 +102,8 @@ export const Button = styled.button` padding: 10px; background: ${({ theme }) => theme.colors.brand.gradient}; `; + +export const ButtonSkeleton = styled.button` + width: 90%; + margin: 16px auto; +`; From 3f0aa01905697c05a8ff4db886eb65b1c16016d2 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 17:20:23 +0900 Subject: [PATCH 14/31] =?UTF-8?q?Refactor:=20profileEdit=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=88=EB=A0=88=ED=86=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Profile/ProfileEdit/index.tsx | 57 +++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/pages/Profile/ProfileEdit/index.tsx b/src/pages/Profile/ProfileEdit/index.tsx index b9eb24a3..f429e18e 100644 --- a/src/pages/Profile/ProfileEdit/index.tsx +++ b/src/pages/Profile/ProfileEdit/index.tsx @@ -15,8 +15,8 @@ import imageBasic from '@assets/default/defaultProfile.svg'; import BottomButton from '@components/BottomButton/index'; import { OODDFrame } from '@components/Frame/Frame'; -import Loading from '@components/Loading/index'; import Modal from '@components/Modal/index'; +import Skeleton from '@components/Skeleton'; import { StyledText } from '@components/Text/StyledText'; import TopBar from '@components/TopBar/index'; @@ -83,7 +83,7 @@ const ProfileEdit: React.FC = () => { } }; - getUserInfo(); + setTimeout(getUserInfo, 1000); }, []); const handleButtonClick = () => { @@ -155,7 +155,56 @@ const ProfileEdit: React.FC = () => { }; if (isLoading || uploading) { - return ; + return ( + + + navigate(-1)} /> + + + + + + + + + 이름 + + + + + + 닉네임 + + + + + + 소개글 + + + + + + 전화번호 + + + + + + 생년월일 + + + + + + 이메일 + + + + + + + ); } return ( @@ -222,7 +271,7 @@ const ProfileEdit: React.FC = () => { setEmail(e.target.value)} /> - +
); From af367ddbdb4f6dd949cc5d1d5500a7def50cb47f Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 17:33:07 +0900 Subject: [PATCH 15/31] =?UTF-8?q?Refactor:=20AccountSetting=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=88=EB=A0=88=ED=86=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Account/AccountSetting/index.tsx | 33 ++++++++++++++++++--- src/pages/Account/AccountSetting/styles.tsx | 7 ++--- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/pages/Account/AccountSetting/index.tsx b/src/pages/Account/AccountSetting/index.tsx index 65ba1624..dcbcdf4d 100644 --- a/src/pages/Account/AccountSetting/index.tsx +++ b/src/pages/Account/AccountSetting/index.tsx @@ -12,8 +12,8 @@ import leave from '@assets/default/leave.svg'; import Profile_s from '@assets/default/my-page.svg'; import { OODDFrame } from '@components/Frame/Frame'; -import Loading from '@components/Loading/index'; import Modal from '@components/Modal'; +import Skeleton from '@components/Skeleton'; import { StyledText } from '@components/Text/StyledText'; import TopBar from '@components/TopBar/index'; @@ -44,8 +44,7 @@ const AccountSetting: React.FC = () => { setIsLoading(false); } }; - - getUserInfo(); + setTimeout(getUserInfo, 1000); }, []); const handleConfirmLogout = () => { @@ -68,7 +67,33 @@ const AccountSetting: React.FC = () => { }; if (isLoading) { - return ; + return ( + + + navigate(-1)} /> + + + + {' '} + + + + + + + + + + + + + + + + + + + ); } return ( diff --git a/src/pages/Account/AccountSetting/styles.tsx b/src/pages/Account/AccountSetting/styles.tsx index 5b1ce005..1a908488 100644 --- a/src/pages/Account/AccountSetting/styles.tsx +++ b/src/pages/Account/AccountSetting/styles.tsx @@ -13,8 +13,6 @@ export const ProfilePicWrapper = styled.div` display: flex; flex-direction: column; align-items: center; - margin-bottom: 1.25rem; - margin-top: 24px; `; export const ProfilePic = styled.div` @@ -24,7 +22,6 @@ export const ProfilePic = styled.div` border-radius: 50%; overflow: hidden; margin-top: 2.125rem; - margin-bottom: 1.375rem; img { width: 100%; @@ -42,7 +39,7 @@ export const Row = styled.div` justify-content: center; align-items: center; width: 100%; - margin-bottom: 10px; + margin-top: 10px; ${Label} { width: auto; @@ -67,7 +64,7 @@ export const List = styled.ul` export const ListItem = styled.li` display: flex; align-items: center; - padding: 15px 1.25rem; + padding: 15px 10px; border-bottom: 0px solid ${({ theme }) => theme.colors.background.divider}; cursor: pointer; From c60e3669049cea4344ff935170a7bc549109c4ce Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 17:37:19 +0900 Subject: [PATCH 16/31] =?UTF-8?q?Refactor:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=8A=A4=EC=BC=88=EB=A0=88=ED=86=A4=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Account/AccountCancel/index.tsx | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/pages/Account/AccountCancel/index.tsx b/src/pages/Account/AccountCancel/index.tsx index 17e4dd2c..5a098877 100644 --- a/src/pages/Account/AccountCancel/index.tsx +++ b/src/pages/Account/AccountCancel/index.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import theme from '@styles/theme'; @@ -11,6 +11,7 @@ import back from '@assets/arrow/left.svg'; import BottomButton from '@components/BottomButton/index'; import { OODDFrame } from '@components/Frame/Frame'; import Modal from '@components/Modal/index'; +import Skeleton from '@components/Skeleton'; import { StyledText } from '@components/Text/StyledText'; import TopBar from '@components/TopBar/index'; @@ -30,8 +31,15 @@ const AccountCancel: React.FC = () => { const [isChecked, setIsChecked] = useState(false); const [modalContent, setModalContent] = useState(null); const [isModalVisible, setIsModalVisible] = useState(false); + const [isLoading, setIsLoading] = useState(true); // Loading state const navigate = useNavigate(); + useEffect(() => { + setTimeout(() => { + setIsLoading(false); + }, 5000); + }, []); + const handleCheckboxChange = () => { setIsChecked(!isChecked); }; @@ -79,6 +87,23 @@ const AccountCancel: React.FC = () => { } }; + if (isLoading) { + return ( + + + navigate(-1)} /> + + + OOTD 탈퇴 전 확인하세요! + + + + + + + ); + } + return ( From f35fc1efb98c86c5d8d74a55e170eaf12ebba409 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 17:40:19 +0900 Subject: [PATCH 17/31] =?UTF-8?q?Fix:=20=EC=82=AC=EC=86=8C=ED=95=9C=20UI?= =?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 --- src/pages/Account/AccountCancel/index.tsx | 2 +- src/pages/Profile/ProfileEdit/index.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/Account/AccountCancel/index.tsx b/src/pages/Account/AccountCancel/index.tsx index 5a098877..9f93c616 100644 --- a/src/pages/Account/AccountCancel/index.tsx +++ b/src/pages/Account/AccountCancel/index.tsx @@ -37,7 +37,7 @@ const AccountCancel: React.FC = () => { useEffect(() => { setTimeout(() => { setIsLoading(false); - }, 5000); + }, 1000); }, []); const handleCheckboxChange = () => { diff --git a/src/pages/Profile/ProfileEdit/index.tsx b/src/pages/Profile/ProfileEdit/index.tsx index f429e18e..f605ec82 100644 --- a/src/pages/Profile/ProfileEdit/index.tsx +++ b/src/pages/Profile/ProfileEdit/index.tsx @@ -160,8 +160,11 @@ const ProfileEdit: React.FC = () => { navigate(-1)} /> - + + + + From 22b5dbc559e5ebe234580e8afb74d8044e86ee5f Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 18:10:03 +0900 Subject: [PATCH 18/31] =?UTF-8?q?Refactor:=20post=EC=97=90=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=88=EB=A0=88=ED=86=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Post/index.tsx | 31 +++++++++++++++++++++++++++++++ src/pages/Post/styles.tsx | 39 ++++++++++++++++----------------------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/pages/Post/index.tsx b/src/pages/Post/index.tsx index ad69bbfd..20a178e0 100644 --- a/src/pages/Post/index.tsx +++ b/src/pages/Post/index.tsx @@ -7,6 +7,7 @@ import { modifyPostRepresentativeStatusApi, deletePostApi } from '@apis/post'; import { isPostRepresentativeAtom, postIdAtom, userAtom } from '@recoil/Post/PostAtom'; import { getCurrentUserId } from '@utils/getCurrentUserId'; +import back from '@assets/arrow/left.svg'; import Delete from '@assets/default/delete.svg'; import Edit from '@assets/default/edit.svg'; import Pin from '@assets/default/pin.svg'; @@ -14,7 +15,10 @@ import Pin from '@assets/default/pin.svg'; import BottomSheet from '@components/BottomSheet'; import BottomSheetMenu from '@components/BottomSheet/BottomSheetMenu'; import OptionsBottomSheet from '@components/BottomSheet/OptionsBottomSheet'; +import { OODDFrame } from '@components/Frame/Frame'; import Modal from '@components/Modal'; +import Skeleton from '@components/Skeleton'; +import TopBar from '@components/TopBar/index'; import type { BottomSheetMenuProps } from '@components/BottomSheet/BottomSheetMenu/dto'; import type { BottomSheetProps } from '@components/BottomSheet/dto'; @@ -23,6 +27,8 @@ import type { ModalProps } from '@components/Modal/dto'; import PostBase from './PostBase/index'; +import { PicWrapper, NameWrapper, InfoWrapper, PostWrapper } from './styles'; + const Post: React.FC = () => { const user = useRecoilValue(userAtom); const postId = useRecoilValue(postIdAtom); @@ -37,6 +43,8 @@ const Post: React.FC = () => { const [modalContent, setModalContent] = useState(''); const [postPinStatus, setPostPinStatus] = useState<'지정' | '해제'>('지정'); + const [isLoading, setIsLoading] = useState(true); + const navigate = useNavigate(); const currentUserId = getCurrentUserId(); @@ -87,6 +95,10 @@ const Post: React.FC = () => { }; useEffect(() => { + setTimeout(() => { + setIsLoading(false); + }, 5000); + // 현재 게시글이 내 게시글인지 확인 if (user?.id && postId) { setIsMyPost(currentUserId === user.id); @@ -163,6 +175,25 @@ const Post: React.FC = () => { content: modalContent, }; + if (isLoading) { + return ( + + navigate(-1)} /> + + + + + + + + + + + + + ); + } + return ( <> diff --git a/src/pages/Post/styles.tsx b/src/pages/Post/styles.tsx index 5e347dfe..0c610fe8 100644 --- a/src/pages/Post/styles.tsx +++ b/src/pages/Post/styles.tsx @@ -1,28 +1,21 @@ import { styled } from 'styled-components'; -export const InputLayout = styled.div` +export const InfoWrapper = styled.div` display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + flex-direction: row; + align-items: left; +`; + +export const PicWrapper = styled.div` + margin-left: 47px; +`; + +export const NameWrapper = styled.div` + margin-left: 10px; + margin-top: 10px; +`; - textarea { - display: block; - width: calc(100% - 3rem); - height: 5.75rem; - border-radius: 0.125rem; - border: 0.0625rem solid ${({ theme }) => theme.colors.gray[600]}; - margin-bottom: 5.875rem; - z-index: 2; - margin-top: -3.75rem; - outline: none; - padding: 0.8125rem 0.9375rem; - font-family: 'Pretendard Variable'; - font-size: 1rem; - font-style: normal; - font-weight: 300; - line-height: 150%; - color: ${({ theme }) => theme.colors.text.primary}; - resize: none; - } +export const PostWrapper = styled.div` + margin-top: 10px; + padding-inline: 30px; `; From ac91e1e64b551fb8dea0c75fd80e9e511c372c07 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Sat, 22 Mar 2025 18:12:31 +0900 Subject: [PATCH 19/31] =?UTF-8?q?Fix:=20=EB=A1=9C=EB=94=A9=ED=83=80?= =?UTF-8?q?=EC=9E=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Post/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Post/index.tsx b/src/pages/Post/index.tsx index 20a178e0..84bd872e 100644 --- a/src/pages/Post/index.tsx +++ b/src/pages/Post/index.tsx @@ -97,7 +97,7 @@ const Post: React.FC = () => { useEffect(() => { setTimeout(() => { setIsLoading(false); - }, 5000); + }, 1000); // 현재 게시글이 내 게시글인지 확인 if (user?.id && postId) { From 1d329a2b10b83164b2176405dec36623c860f004 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:25:45 +0900 Subject: [PATCH 20/31] =?UTF-8?q?Fix:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20rem=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index 085694e5..d79b5d1b 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -17,7 +17,7 @@ const Skeleton: React.FC = ({ // width와 height가 숫자인 경우 rem 단위를 추가 const getSize = (size: string | number) => { if (typeof size === 'number') { - return `${size}px`; + return `${size}rem`; } return size; }; From 2b5d4bae90b14e163af3e5ee74e125d24548daf3 Mon Sep 17 00:00:00 2001 From: Ajin Park <108174693+lalaurrel@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:26:04 +0900 Subject: [PATCH 21/31] =?UTF-8?q?Fix:=20rem=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Account/AccountCancel/index.tsx | 2 +- src/pages/Account/AccountSetting/index.tsx | 10 +++++----- src/pages/Post/index.tsx | 6 +++--- src/pages/Profile/ProfileEdit/index.tsx | 16 ++++++++-------- src/pages/Profile/index.tsx | 16 ++++++++-------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/pages/Account/AccountCancel/index.tsx b/src/pages/Account/AccountCancel/index.tsx index 9f93c616..61adba0f 100644 --- a/src/pages/Account/AccountCancel/index.tsx +++ b/src/pages/Account/AccountCancel/index.tsx @@ -95,7 +95,7 @@ const AccountCancel: React.FC = () => { OOTD 탈퇴 전 확인하세요! - + diff --git a/src/pages/Account/AccountSetting/index.tsx b/src/pages/Account/AccountSetting/index.tsx index dcbcdf4d..efadc1f0 100644 --- a/src/pages/Account/AccountSetting/index.tsx +++ b/src/pages/Account/AccountSetting/index.tsx @@ -73,22 +73,22 @@ const AccountSetting: React.FC = () => { navigate(-1)} /> - + {' '} - + - + - + - + diff --git a/src/pages/Post/index.tsx b/src/pages/Post/index.tsx index 84bd872e..dfae0030 100644 --- a/src/pages/Post/index.tsx +++ b/src/pages/Post/index.tsx @@ -181,14 +181,14 @@ const Post: React.FC = () => { navigate(-1)} /> - + - + - + ); diff --git a/src/pages/Profile/ProfileEdit/index.tsx b/src/pages/Profile/ProfileEdit/index.tsx index f605ec82..28676c02 100644 --- a/src/pages/Profile/ProfileEdit/index.tsx +++ b/src/pages/Profile/ProfileEdit/index.tsx @@ -161,48 +161,48 @@ const ProfileEdit: React.FC = () => { navigate(-1)} /> - + - + 이름 - + 닉네임 - + 소개글 - + 전화번호 - + 생년월일 - + 이메일 - + diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx index 4637742c..87397d4d 100644 --- a/src/pages/Profile/index.tsx +++ b/src/pages/Profile/index.tsx @@ -128,38 +128,38 @@ const Profile: React.FC = () => {
{/* 프로필 섹션 스켈레톤 */} - + - - + +
{/* 버튼 스켈레톤 */} - + {/* 통계 스켈레톤 */} - + {isMyPage && ( - + )} - + {/* 포스트 스켈레톤 */} {[1, 2, 3, 4].map((item) => ( - + ))} From 6dc8812b3cdcfeca05e68cb44a9b4819d9b9d00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=EB=AF=BC=EC=9E=AC?= Date: Fri, 28 Mar 2025 22:08:23 +0900 Subject: [PATCH 22/31] =?UTF-8?q?feat:=20react-query=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + yarn.lock | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/package.json b/package.json index 099fc075..b92f9b92 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "start:json-server": "json-server --watch db.json --port 5000" }, "dependencies": { + "@tanstack/react-query": "^5.69.3", "@types/styled-components": "^5.1.34", "axios": "^1.7.2", "dayjs": "^1.11.12", diff --git a/yarn.lock b/yarn.lock index e7af7353..7172de3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -995,6 +995,18 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== +"@tanstack/query-core@5.69.2": + version "5.69.2" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.69.2.tgz#65d4fa172c48aa1549661b0442df6c44281a08e9" + integrity sha512-+spKBqGMSxVMhYPMHr4L7efc4CDdb0Y8nE4UxP/FjV4V3ajP3uhBsh0T7pSuObBgYkU+nY1PRkJhKNmwlHmkUg== + +"@tanstack/react-query@^5.69.3": + version "5.69.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.69.3.tgz#30b49a99af412a518babc61fe7dfa12625c3776a" + integrity sha512-EozCj1aFM/c827GQbVnvEt2x80oBax1vd2e5s/2EDeD469AZW9BPAyRK9VVyD0I1yvO6vOI+tPKXXFcadbSXvA== + dependencies: + "@tanstack/query-core" "5.69.2" + "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" From b8299f3f8c5a5ee258674bddd778b5666d8c74f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=EB=AF=BC=EC=9E=AC?= Date: Fri, 28 Mar 2025 22:16:32 +0900 Subject: [PATCH 23/31] =?UTF-8?q?feat:=20query=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=20=ED=95=A8=EC=88=98=EB=A1=9C=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/App.tsx | 37 +++++++++++++++++++++---------------- src/apis/post/index.ts | 6 ++++-- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 28bea8f1..f987ad94 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import Home from '@pages/Home'; import Login from '@pages/Login'; @@ -32,6 +33,8 @@ import { getUserInfoApi } from '@apis/user'; import { getCurrentUserId } from '@utils/getCurrentUserId'; import Loading from '@components/Loading'; +const queryClient = new QueryClient(); + const ProtectedRoute = ({ children }: { children: JSX.Element }) => { const [isAuthenticated, setIsAuthenticated] = useState(null); @@ -98,22 +101,24 @@ const publicRoutes = [ const App: React.FC = () => { return ( - - - {/* 인증이 필요한 페이지 */} - {protectedRoutes.map(({ path, element }) => ( - {element}} /> - ))} - - {/* 인증이 필요 없는 페이지 */} - {publicRoutes.map(({ path, element }) => ( - - ))} - - {/* 없는 페이지에 대한 처리 */} - } /> - - + + + + {/* 인증이 필요한 페이지 */} + {protectedRoutes.map(({ path, element }) => ( + {element}} /> + ))} + + {/* 인증이 필요 없는 페이지 */} + {publicRoutes.map(({ path, element }) => ( + + ))} + + {/* 없는 페이지에 대한 처리 */} + } /> + + + ); }; diff --git a/src/apis/post/index.ts b/src/apis/post/index.ts index 18614464..758a668e 100644 --- a/src/apis/post/index.ts +++ b/src/apis/post/index.ts @@ -17,8 +17,10 @@ export const createPostApi = (data: CreatePostRequest) => newRequest.post - newRequest.get(`/post`, { params: { page, take } }); +export const getPostListApi = async (page: number = 1, take: number = 10) => { + const { data } = await newRequest.get(`/post`, { params: { page, take } }); + return data; +}; // 유저 게시글 리스트 export const getUserPostListApi = (page: number = 1, take: number = 10, userId: number) => newRequest.get(`/post`, { params: { page, take, userId } }); From b3bc3bf6138e6184b4fbd6f724268ba9b9651079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=EB=AF=BC=EC=9E=AC?= Date: Fri, 28 Mar 2025 22:53:42 +0900 Subject: [PATCH 24/31] =?UTF-8?q?doc:=20=EC=9D=B4=ED=95=B4=EB=A5=BC=20?= =?UTF-8?q?=EB=8F=95=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=EC=A3=BC=EC=84=9D=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/apis/post/index.ts | 11 +++- src/pages/Home/OOTD/index.tsx | 112 ++++++++++++---------------------- 2 files changed, 47 insertions(+), 76 deletions(-) diff --git a/src/apis/post/index.ts b/src/apis/post/index.ts index 758a668e..2adb94fd 100644 --- a/src/apis/post/index.ts +++ b/src/apis/post/index.ts @@ -17,9 +17,14 @@ export const createPostApi = (data: CreatePostRequest) => newRequest.post { - const { data } = await newRequest.get(`/post`, { params: { page, take } }); - return data; +export const getPostListApi = async ({ pageParam = 1 }) => { + const response = await newRequest.get('/post', { + params: { page: pageParam, take: 20 }, + }); + return { + posts: response.data.post, + nextPage: response.data.post.length > 0 ? pageParam + 1 : undefined, // 다음 페이지 여부 확인 + }; }; // 유저 게시글 리스트 export const getUserPostListApi = (page: number = 1, take: number = 10, userId: number) => diff --git a/src/pages/Home/OOTD/index.tsx b/src/pages/Home/OOTD/index.tsx index edf31e5b..c1b8da5e 100644 --- a/src/pages/Home/OOTD/index.tsx +++ b/src/pages/Home/OOTD/index.tsx @@ -1,72 +1,51 @@ -import { useState, useEffect, useRef } from 'react'; +import { useRef, useEffect } from 'react'; +import { useInfiniteQuery } from '@tanstack/react-query'; import debounce from 'lodash/debounce'; import { getPostListApi } from '@apis/post'; -import type { PostSummary } from '@apis/post/dto'; +import Loading from '@components/Loading'; import Feed from './Feed/index'; import { OOTDContainer, FeedContainer } from './styles'; const OOTD: React.FC = () => { - const [feeds, setFeeds] = useState([]); - - const isFetchingRef = useRef(false); - const isReachedEndRef = useRef(false); - const feedPageRef = useRef(1); - - // IntersectionObserver 인스턴스를 참조하는 변수 - const observerRef = useRef(null); - // observer 콜백 함수를 트리거하는 요소를 참조하는 변수 + // 무한 스크롤을 감지할 요소 const loadMoreRef = useRef(null); - // 세션 스토리지에서 이전 스크롤 위치를 가져와 초기화 - const savedScrollPosition = sessionStorage.getItem('scrollPosition'); - const scrollPositionRef = useRef(Number(savedScrollPosition) || 0); - - // 전체 게시글(피드) 조회 API - const getPostList = async () => { - // 모든 데이터를 불러왔거나 요청 중이라면 함수 실행 중단 - if (isReachedEndRef.current || isFetchingRef.current) return; - - isFetchingRef.current = true; - - try { - const response = await getPostListApi(feedPageRef.current, 20); + // Intersection Observer 인스턴스 저장 (컴포넌트 언마운트 시 해제 위함) + const observerRef = useRef(null); - if (response.isSuccess) { - if (response.data.post.length === 0) { - isReachedEndRef.current = true; - } else { - setFeeds((prevFeeds) => [...prevFeeds, ...response.data.post]); - feedPageRef.current += 1; - } - } - } finally { - isFetchingRef.current = false; - console.log(feeds); - } - }; + // React Query를 사용한 무한 스크롤 데이터 로드 + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } = useInfiniteQuery({ + queryKey: ['posts'], // 같은 key를 가진 쿼리는 캐시됨 + queryFn: ({ pageParam }) => getPostListApi({ pageParam }), // 페이지별 데이터 가져오는 함수 + initialPageParam: 1, // 첫 번째 페이지는 1부터 시작 + getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined, // 다음 페이지가 존재하면 page + 1, 없으면 undefined + }); + // 디버깅 useEffect(() => { - // 데이터의 끝에 다다르면 옵저버 해제 (더이상 피드가 없으면) - if (isReachedEndRef.current && observerRef.current && loadMoreRef.current) { - observerRef.current.unobserve(loadMoreRef.current); + console.log('Query Status:', status); + console.log('Fetched Data:', data); + console.log('Fetching Next Page:', isFetchingNextPage); + console.log('Has Next Page:', hasNextPage); + }, [status, data, isFetchingNextPage, hasNextPage]); - return; - } + // Intersection Observer를 설정하여 스크롤이 마지막 요소에 닿았을 때 fetchNextPage 호출 + useEffect(() => { + if (!loadMoreRef.current || !hasNextPage) return; // 다음 페이지가 없으면 실행 X // Intersection Observer 생성 observerRef.current = new IntersectionObserver( debounce((entries) => { - const target = entries[0]; - console.log('Intersection Observer:', target.isIntersecting); - if (target.isIntersecting && !isFetchingRef.current && !isReachedEndRef.current) { - getPostList(); + // 요소가 화면에 보이면 fetchNextPage 호출 (스크롤 트리거) + if (entries[0].isIntersecting) { + fetchNextPage(); } - }, 300), + }, 300), // 디바운싱 적용 (300ms 내 반복 호출 방지) { root: null, rootMargin: '100px', @@ -74,40 +53,27 @@ const OOTD: React.FC = () => { }, ); - // 옵저버를 마지막 요소에 연결 - if (loadMoreRef.current) { - observerRef.current.observe(loadMoreRef.current); - } - return () => { - // 컴포넌트 언마운트 시 옵저버 해제 - if (observerRef.current && loadMoreRef.current) { - observerRef.current.unobserve(loadMoreRef.current); - } - }; - }, []); - - useEffect(() => { - getPostList(); - - // 세션에 저장된 이전 스크롤 위치 복원 - window.scrollTo(0, scrollPositionRef.current); + // 옵저버를 마지막 요소(loadMoreRef)에 연결 + observerRef.current.observe(loadMoreRef.current); return () => { - // 컴포넌트 언마운트 시 현재 스크롤 위치를 세션 스토리지에 저장 - sessionStorage.setItem('scrollPosition', String(window.scrollY)); + // 컴포넌트 언마운트 시 옵저버 해제 + observerRef.current?.disconnect(); }; - }, []); + }, [hasNextPage, fetchNextPage]); return ( - {feeds.map((feed) => ( -
- -
- ))} - {/* Intersection Observer가 감지할 마지막 요소 */} + {data?.pages.flatMap((page) => + page.posts.map((feed) => ( +
+ +
+ )), + )}
+ {isFetchingNextPage && } ); From 3ca91e58382b24905d1a18887275b8f6ebad86e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=EB=AF=BC=EC=9E=AC?= Date: Fri, 28 Mar 2025 23:13:00 +0900 Subject: [PATCH 25/31] =?UTF-8?q?chore:=20=ED=95=9C=20=EB=B2=88=EC=97=90?= =?UTF-8?q?=20=EB=B6=88=EB=9F=AC=EC=99=80=EC=A7=80=EB=8A=94=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=88=98=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/post/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apis/post/index.ts b/src/apis/post/index.ts index 2adb94fd..0d7721fe 100644 --- a/src/apis/post/index.ts +++ b/src/apis/post/index.ts @@ -19,7 +19,7 @@ export const createPostApi = (data: CreatePostRequest) => newRequest.post { const response = await newRequest.get('/post', { - params: { page: pageParam, take: 20 }, + params: { page: pageParam, take: 10 }, }); return { posts: response.data.post, From 8f728a159d8077899dbe74a13eaa5fd24994bd5f Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 12:35:24 +0900 Subject: [PATCH 26/31] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4UI=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20setTimeout=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Post/index.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/Post/index.tsx b/src/pages/Post/index.tsx index dfae0030..ba629df2 100644 --- a/src/pages/Post/index.tsx +++ b/src/pages/Post/index.tsx @@ -95,14 +95,11 @@ const Post: React.FC = () => { }; useEffect(() => { - setTimeout(() => { - setIsLoading(false); - }, 1000); - // 현재 게시글이 내 게시글인지 확인 if (user?.id && postId) { setIsMyPost(currentUserId === user.id); } + setIsLoading(false); }, [user, postId]); useEffect(() => { From 86cb993444e50d0de37032424eeb441d30df73de Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 15:00:33 +0900 Subject: [PATCH 27/31] =?UTF-8?q?chore:=20react-query=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 ++ src/main.tsx | 19 +++++++++++++------ yarn.lock | 24 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 099fc075..fb2b0cb8 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "start:json-server": "json-server --watch db.json --port 5000" }, "dependencies": { + "@tanstack/react-query": "^5.70.0", + "@tanstack/react-query-devtools": "^5.70.0", "@types/styled-components": "^5.1.34", "axios": "^1.7.2", "dayjs": "^1.11.12", diff --git a/src/main.tsx b/src/main.tsx index 223211e3..f5a1814c 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,3 +1,5 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { createRoot } from 'react-dom/client'; import { RecoilRoot } from 'recoil'; import { ThemeProvider } from 'styled-components'; @@ -10,13 +12,18 @@ import { SocketProvider } from '@context/SocketProvider'; import App from './App'; +const queryClient = new QueryClient(); + createRoot(document.getElementById('root')!).render( - - - - - - + + + + + + + + + , ); diff --git a/yarn.lock b/yarn.lock index e7af7353..d627b042 100644 --- a/yarn.lock +++ b/yarn.lock @@ -995,6 +995,30 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== +"@tanstack/query-core@5.70.0": + version "5.70.0" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.70.0.tgz#fb092c657440f38e5f5af570679ee1d7273ab5f4" + integrity sha512-ZkkjQAZjI6nS5OyAmaSQafQXK180Xvp0lZYk4BzrnskkTV8On3zSJUxOIXnh0h/8EgqRkCA9i879DiJovA1kGw== + +"@tanstack/query-devtools@5.67.2": + version "5.67.2" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.67.2.tgz#890ae9913bd21d3969c7fd85c68b1bd1500cfc57" + integrity sha512-O4QXFFd7xqp6EX7sdvc9tsVO8nm4lpWBqwpgjpVLW5g7IeOY6VnS/xvs/YzbRhBVkKTMaJMOUGU7NhSX+YGoNg== + +"@tanstack/react-query-devtools@^5.70.0": + version "5.70.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.70.0.tgz#a9b2067ed2b6ec9668552a8d29804f574d48183f" + integrity sha512-jFtpA3mnUoVn/ic1EVxmA6qG7z8S19nchsHciMCWOvC1Z2Mt8f0wbl1p8hNvrBpzWywZa+Hl0AxMVs48psUvhg== + dependencies: + "@tanstack/query-devtools" "5.67.2" + +"@tanstack/react-query@^5.70.0": + version "5.70.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.70.0.tgz#5130b38b7f2354b97de6b256c008b24a50885743" + integrity sha512-z0tx1zz2CQ6nTm+fCaOp93FqsFjNgXtOy+4mC5ifQ4B+rJiMD0AGfJrYSGh/OuefhrzTYDAbkGUAGw6JzkWy8g== + dependencies: + "@tanstack/query-core" "5.70.0" + "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" From 6113031c9948f612efeb92d605f4d4d0e1adde18 Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 15:01:28 +0900 Subject: [PATCH 28/31] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20api=EB=A5=BC=20=EA=B0=90=EC=8B=B8=EB=8A=94=20react-query=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/post/index.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/apis/post/index.ts b/src/apis/post/index.ts index 18614464..0b88452d 100644 --- a/src/apis/post/index.ts +++ b/src/apis/post/index.ts @@ -1,3 +1,5 @@ +import { useQuery } from '@tanstack/react-query'; + import { newRequest } from '@apis/core'; import type { EmptySuccessResponse } from '@apis/core/dto'; @@ -36,3 +38,11 @@ export const deletePostApi = (postId: number) => newRequest.delete newRequest.patch(`/post/${postId}/is-representative`); + +export const usePostDetail = (postId: number) => { + return useQuery({ + queryKey: ['postDetail', postId], + queryFn: () => getPostDetailApi(postId), + enabled: !!postId, // postId가 존재할 때만 요청 수행 + }); +}; From 433648c2af7229b32c896b9f52fb04d58812fcc6 Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 15:01:58 +0900 Subject: [PATCH 29/31] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=A2=8B=EC=95=84=EC=9A=94=20&=20=EC=B7=A8=EC=86=8C=20api?= =?UTF-8?q?=EB=8F=84=20react-query=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=B4?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Post/PostBase/index.tsx | 87 ++++++++++++------------------- 1 file changed, 33 insertions(+), 54 deletions(-) diff --git a/src/pages/Post/PostBase/index.tsx b/src/pages/Post/PostBase/index.tsx index 990daa75..9b4a332f 100644 --- a/src/pages/Post/PostBase/index.tsx +++ b/src/pages/Post/PostBase/index.tsx @@ -1,15 +1,14 @@ import { useEffect, useState, useRef } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import dayjs from 'dayjs'; -import { useRecoilState } from 'recoil'; -import 'dayjs/locale/ko'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import dayjs, { extend } from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; import theme from '@styles/theme'; -import { getPostDetailApi } from '@apis/post'; +import { usePostDetail } from '@apis/post'; import { togglePostLikeStatusApi } from '@apis/post-like'; -import { postIdAtom, userAtom, isPostRepresentativeAtom } from '@recoil/Post/PostAtom'; import Left from '@assets/arrow/left.svg'; import Message from '@assets/default/message.svg'; @@ -51,11 +50,7 @@ import { } from './styles'; const PostBase: React.FC = ({ onClickMenu }) => { - const [, setPostId] = useRecoilState(postIdAtom); - const [post, setPost] = useState(); - const [user, setUser] = useRecoilState(userAtom); - const [, setIsPostRepresentative] = useRecoilState(isPostRepresentativeAtom); - const [timeAgo, setTimeAgo] = useState(); + extend(relativeTime); const [isTextOverflowing, setIsTextOverflowing] = useState(false); const [showFullText, setShowFullText] = useState(false); const [isLikeCommentBottomSheetOpen, setIsLikeCommentBottomSheetOpen] = useState(false); @@ -64,6 +59,12 @@ const PostBase: React.FC = ({ onClickMenu }) => { const { postId } = useParams<{ postId: string }>(); const contentRef = useRef(null); + const { data } = usePostDetail(Number(postId)); + const queryClient = useQueryClient(); + const post = data?.data; + const user = post?.user; + const timeAgo = dayjs(post?.createdAt).locale('ko').fromNow(); + const nav = useNavigate(); const handleLikeCommentOpen = (tab: 'likes' | 'comments') => { @@ -80,48 +81,26 @@ const PostBase: React.FC = ({ onClickMenu }) => { }; // 게시글 좋아요 누르기/취소하기 api - const togglePostLikeStatus = async () => { - if (!post || !postId) return; - - const prevPost = { ...post }; // 현재 상태 저장 - setPost({ - ...post, - isPostLike: !post.isPostLike, - postLikesCount: post.isPostLike ? post.postLikesCount - 1 : post.postLikesCount + 1, - }); //사용자가 좋아요를 누르면 먼저 클라이언트에서 post 상태를 변경(낙관적 업데이트) - - try { - const response = await togglePostLikeStatusApi(Number(postId)); - setPost({ - ...post, - isPostLike: response.data.isPostLike, - postLikesCount: response.data.postLikesCount, - }); // 서버로 요청 후 성공하면 그대로 유지 - } catch (error) { - console.error('Error toggling like status:', error); - setPost(prevPost); // 실패하면 원래 상태로 롤백 - } - }; - - useEffect(() => { - setPostId(Number(postId)); - - // 게시글 정보 가져오기 - const getPost = async () => { - try { - const response = await getPostDetailApi(Number(postId)); - const data = response.data; - setPost(data); - setUser(data.user); - setIsPostRepresentative(data.isRepresentative); - setTimeAgo(dayjs(data.createdAt).locale('ko').fromNow()); - } catch (error) { - console.error('Error fetching post data:', error); - } - }; - - getPost(); - }, [postId]); + const { mutate: togglePostLikeStatus } = useMutation({ + mutationFn: () => togglePostLikeStatusApi(Number(postId)), + onSuccess: () => { + queryClient.setQueryData(['postDetail', Number(postId)], (oldData: GetPostDetailResponse | undefined) => { + if (!oldData) return oldData; + + const newData = { + ...oldData, + data: { + ...oldData.data, + postLikesCount: oldData.data.postLikesCount + (oldData.data.isPostLike ? -1 : 1), // 기존 좋아요 개수를 토대로 증가/감소 + isPostLike: !oldData.data.isPostLike, // 좋아요 상태 변경 + }, + }; + console.log('newData', newData); + + return newData; + }); + }, + }); useEffect(() => { if (contentRef.current) { @@ -160,7 +139,7 @@ const PostBase: React.FC = ({ onClickMenu }) => { $textTheme={{ style: 'body2-medium' }} color={theme.colors.text.primary} > - {user.nickname} + {user?.nickname ?? '알수없음'} = ({ onClickMenu }) => { - + togglePostLikeStatus()}> {post?.isPostLike ? : } handleLikeCommentOpen('likes')}>{post?.postLikesCount ?? 0} From e5099d52574c0702f8657cc0e63b02754519a5ac Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 15:15:41 +0900 Subject: [PATCH 30/31] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20UI=EB=A5=BC=20PostBase=EC=97=90=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 --- src/pages/Post/PostBase/index.tsx | 34 ++++++++++++++++----- src/pages/Post/PostBase/styles.tsx | 47 ++++++++---------------------- src/pages/Post/index.tsx | 28 ------------------ src/pages/Post/styles.tsx | 10 ------- 4 files changed, 38 insertions(+), 81 deletions(-) diff --git a/src/pages/Post/PostBase/index.tsx b/src/pages/Post/PostBase/index.tsx index 9b4a332f..2a421fdb 100644 --- a/src/pages/Post/PostBase/index.tsx +++ b/src/pages/Post/PostBase/index.tsx @@ -20,6 +20,7 @@ import BottomSheet from '@components/BottomSheet'; import ClothingInfoItem from '@components/ClothingInfoItem'; import { OODDFrame } from '@components/Frame/Frame'; import NavBar from '@components/NavBar'; +import Skeleton from '@components/Skeleton'; import { StyledText } from '@components/Text/StyledText'; import TopBar from '@components/TopBar'; @@ -39,14 +40,14 @@ import { UserName, MenuBtn, PostContentContainer, - ContentSkeleton, Content, ShowMoreButton, - ImageSkeleton, IconRow, IconWrapper, Icon, ClothingInfoList, + UserNameWrapper, + PostWrapper, } from './styles'; const PostBase: React.FC = ({ onClickMenu }) => { @@ -59,7 +60,7 @@ const PostBase: React.FC = ({ onClickMenu }) => { const { postId } = useParams<{ postId: string }>(); const contentRef = useRef(null); - const { data } = usePostDetail(Number(postId)); + const { data, isLoading } = usePostDetail(Number(postId)); const queryClient = useQueryClient(); const post = data?.data; const user = post?.user; @@ -124,6 +125,25 @@ const PostBase: React.FC = ({ onClickMenu }) => { }, }; + if (isLoading) { + return ( + + nav(-1)} /> + + + + + + + + + + + + + ); + } + return ( @@ -132,7 +152,7 @@ const PostBase: React.FC = ({ onClickMenu }) => { - {post?.user && profileImg} + {user && profileImg} = ({ onClickMenu }) => { - {!post ? : image.url)} />} + {post && image.url)} />} {post?.postClothings && ( @@ -179,9 +199,7 @@ const PostBase: React.FC = ({ onClickMenu }) => { - {!post ? ( - - ) : ( + {post && (
theme.colors.gray[200]} 25%, - ${({ theme }) => theme.colors.gray[300]} 50%, - ${({ theme }) => theme.colors.gray[200]} 75% - ); - background-size: 200% 100%; - animation: ${shimmer} 2s infinite; -`; - export const PostLayout = styled.div` display: flex; flex-direction: column; @@ -73,7 +51,7 @@ export const PostInfoContainer = styled.div` } `; -export const UserProfile = styled(LoadingSkeleton)` +export const UserProfile = styled.button` cursor: pointer; width: 32px; height: 32px; @@ -102,12 +80,6 @@ export const PostContentContainer = styled.div` padding: 0 20px; `; -export const ContentSkeleton = styled(LoadingSkeleton)` - width: 100%; - height: 16px; - border-radius: 4px; -`; - export const Content = styled(StyledText)<{ $showFullText: boolean }>` word-wrap: break-word; word-break: break-all; @@ -125,11 +97,6 @@ export const ShowMoreButton = styled(StyledText)` color: ${({ theme }) => theme.colors.text.tertiary}; `; -export const ImageSkeleton = styled(LoadingSkeleton)` - width: 100%; - aspect-ratio: 4 / 5; -`; - export const IconRow = styled.div` display: flex; height: 20px; @@ -201,3 +168,13 @@ export const InputLayout = styled.div` resize: none; } `; + +export const UserNameWrapper = styled.div` + margin-left: 10px; + margin-top: 10px; +`; + +export const PostWrapper = styled.div` + margin-top: 10px; + padding-inline: 30px; +`; diff --git a/src/pages/Post/index.tsx b/src/pages/Post/index.tsx index ba629df2..ad69bbfd 100644 --- a/src/pages/Post/index.tsx +++ b/src/pages/Post/index.tsx @@ -7,7 +7,6 @@ import { modifyPostRepresentativeStatusApi, deletePostApi } from '@apis/post'; import { isPostRepresentativeAtom, postIdAtom, userAtom } from '@recoil/Post/PostAtom'; import { getCurrentUserId } from '@utils/getCurrentUserId'; -import back from '@assets/arrow/left.svg'; import Delete from '@assets/default/delete.svg'; import Edit from '@assets/default/edit.svg'; import Pin from '@assets/default/pin.svg'; @@ -15,10 +14,7 @@ import Pin from '@assets/default/pin.svg'; import BottomSheet from '@components/BottomSheet'; import BottomSheetMenu from '@components/BottomSheet/BottomSheetMenu'; import OptionsBottomSheet from '@components/BottomSheet/OptionsBottomSheet'; -import { OODDFrame } from '@components/Frame/Frame'; import Modal from '@components/Modal'; -import Skeleton from '@components/Skeleton'; -import TopBar from '@components/TopBar/index'; import type { BottomSheetMenuProps } from '@components/BottomSheet/BottomSheetMenu/dto'; import type { BottomSheetProps } from '@components/BottomSheet/dto'; @@ -27,8 +23,6 @@ import type { ModalProps } from '@components/Modal/dto'; import PostBase from './PostBase/index'; -import { PicWrapper, NameWrapper, InfoWrapper, PostWrapper } from './styles'; - const Post: React.FC = () => { const user = useRecoilValue(userAtom); const postId = useRecoilValue(postIdAtom); @@ -43,8 +37,6 @@ const Post: React.FC = () => { const [modalContent, setModalContent] = useState(''); const [postPinStatus, setPostPinStatus] = useState<'지정' | '해제'>('지정'); - const [isLoading, setIsLoading] = useState(true); - const navigate = useNavigate(); const currentUserId = getCurrentUserId(); @@ -99,7 +91,6 @@ const Post: React.FC = () => { if (user?.id && postId) { setIsMyPost(currentUserId === user.id); } - setIsLoading(false); }, [user, postId]); useEffect(() => { @@ -172,25 +163,6 @@ const Post: React.FC = () => { content: modalContent, }; - if (isLoading) { - return ( - - navigate(-1)} /> - - - - - - - - - - - - - ); - } - return ( <> diff --git a/src/pages/Post/styles.tsx b/src/pages/Post/styles.tsx index 0c610fe8..40a02ee2 100644 --- a/src/pages/Post/styles.tsx +++ b/src/pages/Post/styles.tsx @@ -9,13 +9,3 @@ export const InfoWrapper = styled.div` export const PicWrapper = styled.div` margin-left: 47px; `; - -export const NameWrapper = styled.div` - margin-left: 10px; - margin-top: 10px; -`; - -export const PostWrapper = styled.div` - margin-top: 10px; - padding-inline: 30px; -`; From f6bb38f15b49a521545e1855d93c890a58fcb449 Mon Sep 17 00:00:00 2001 From: young Date: Sat, 29 Mar 2025 16:37:52 +0900 Subject: [PATCH 31/31] =?UTF-8?q?style:=20PostBase=20UI=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Post/PostBase/index.tsx | 155 ++++++++++++++--------------- src/pages/Post/PostBase/styles.tsx | 30 ++---- 2 files changed, 82 insertions(+), 103 deletions(-) diff --git a/src/pages/Post/PostBase/index.tsx b/src/pages/Post/PostBase/index.tsx index 2a421fdb..a68a9835 100644 --- a/src/pages/Post/PostBase/index.tsx +++ b/src/pages/Post/PostBase/index.tsx @@ -34,7 +34,6 @@ import LikeCommentBottomSheetContent from './LikeCommentBottomSheetContent/index import { PostLayout, - PostContainer, PostInfoContainer, UserProfile, UserName, @@ -129,17 +128,19 @@ const PostBase: React.FC = ({ onClickMenu }) => { return ( nav(-1)} /> - - - - - - - - - - - + + + + + + + + + + + + + ); } @@ -149,76 +150,70 @@ const PostBase: React.FC = ({ onClickMenu }) => { - - - - {user && profileImg} - - - {user?.nickname ?? '알수없음'} - - - {timeAgo} - - - more - - - - {post && image.url)} />} + + + {user && profileImg} + + + {user?.nickname ?? '알수없음'} + + + {timeAgo} + + + more + + - {post?.postClothings && ( - - {post.postClothings.map((clothingObj, index) => ( - - ))} - + {post && ( + + image.url)} /> + + )} + + {post?.postClothings ? ( + + {post.postClothings.map((clothingObj, index) => ( + + ))} + + ) : null} + + + + togglePostLikeStatus()}> + {post?.isPostLike ? : } + + handleLikeCommentOpen('likes')}>{post?.postLikesCount ?? 0} + + handleLikeCommentOpen('comments')}> + + message + + {post?.postCommentsCount ?? 0} + + + + + {post && ( +
+ + {post.content} + + {isTextOverflowing && ( + + {showFullText ? '간략히 보기' : '더 보기'} + + )} +
)} - - - - togglePostLikeStatus()}> - {post?.isPostLike ? : } - - handleLikeCommentOpen('likes')}>{post?.postLikesCount ?? 0} - - handleLikeCommentOpen('comments')}> - - message - - {post?.postCommentsCount ?? 0} - - - - - {post && ( -
- - {post.content} - - {isTextOverflowing && ( - - {showFullText ? '간략히 보기' : '더 보기'} - - )} -
- )} -
-
+
diff --git a/src/pages/Post/PostBase/styles.tsx b/src/pages/Post/PostBase/styles.tsx index 1047fb37..edce88cb 100644 --- a/src/pages/Post/PostBase/styles.tsx +++ b/src/pages/Post/PostBase/styles.tsx @@ -6,26 +6,13 @@ export const PostLayout = styled.div` display: flex; flex-direction: column; align-items: center; - width: 100%; - height: 100%; - height: calc(100vh - 2.75rem); - overflow-y: scroll; - - scrollbar-width: none; // Firefox - -ms-overflow-style: none; // IE 10+ - &::-webkit-scrollbar { - display: none; // Safari & Chrome - } -`; + gap: 16px; -export const PostContainer = styled.div` - display: flex; - flex-direction: column; width: 100%; - max-width: 450px; - height: 100%; + height: calc(100vh - 2.75rem); + padding: 0 20px; + padding-bottom: 6.5rem; overflow-y: scroll; - gap: 16px; scrollbar-width: none; // Firefox -ms-overflow-style: none; // IE 10+ @@ -42,7 +29,6 @@ export const PostInfoContainer = styled.div` display: flex; align-items: center; margin-top: 8px; - padding: 0 20px; gap: 8px; align-self: stretch; @@ -77,7 +63,6 @@ export const MenuBtn = styled.button` export const PostContentContainer = styled.div` width: 100%; - padding: 0 20px; `; export const Content = styled(StyledText)<{ $showFullText: boolean }>` @@ -101,7 +86,7 @@ export const IconRow = styled.div` display: flex; height: 20px; align-items: center; - padding: 0 20px; + margin-right: auto; gap: 16px; `; @@ -127,8 +112,8 @@ export const Icon = styled.div` `; export const ClothingInfoList = styled.div` - padding: 0 20px; display: flex; + margin-right: auto; flex-shrink: 0; overflow-x: auto; white-space: nowrap; @@ -175,6 +160,5 @@ export const UserNameWrapper = styled.div` `; export const PostWrapper = styled.div` - margin-top: 10px; - padding-inline: 30px; + width: 100%; `;