From 55958d8f5182c968e4e63e7de415dc3cbeadb94c Mon Sep 17 00:00:00 2001 From: heeyongKim <166043860+heeeeyong@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:00:31 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=A1=9C=EB=94=A9=20=EC=B5=9C=EC=A0=81=ED=99=94=20?= =?UTF-8?q?=EB=B0=8F=20FollowerList=EC=97=90=20=EC=9D=98=ED=95=9C=20CLS=20?= =?UTF-8?q?=EC=99=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/Post/PostBody.tsx | 16 ++++-- src/components/feed/FollowList.styled.ts | 52 +++++++++++++++++++ src/components/feed/FollowList.tsx | 49 ++++++++++++++--- src/components/feed/MyFeed.styled.ts | 1 - src/components/feed/TotalFeed.styled.ts | 2 +- src/components/feed/TotalFeed.tsx | 2 - src/pages/feed/Feed.styled.ts | 2 +- src/pages/feed/Feed.tsx | 14 ++++- .../Skeleton/feed/OtherFeedSkeleton.styled.ts | 2 +- 9 files changed, 123 insertions(+), 17 deletions(-) diff --git a/src/components/common/Post/PostBody.tsx b/src/components/common/Post/PostBody.tsx index 7d224c16..83c6f07a 100644 --- a/src/components/common/Post/PostBody.tsx +++ b/src/components/common/Post/PostBody.tsx @@ -12,7 +12,8 @@ const PostBody = ({ feedId, contentUrls = [], }: PostBodyProps) => { - const hasImage = contentUrls.length > 0; + const previewImages = contentUrls.slice(0, 3); + const hasImage = previewImages.length > 0; const contentRef = useRef(null); const [isTruncated, setIsTruncated] = useState(false); @@ -43,8 +44,17 @@ const PostBody = ({ {hasImage && ( <> - {contentUrls.map((src: string, i: number) => ( - + {previewImages.map((src: string, i: number) => ( + {`피드 ))} )} diff --git a/src/components/feed/FollowList.styled.ts b/src/components/feed/FollowList.styled.ts index d3787553..b9a4c5a9 100644 --- a/src/components/feed/FollowList.styled.ts +++ b/src/components/feed/FollowList.styled.ts @@ -14,10 +14,30 @@ export const Container = styled.div` .title { display: flex; flex-direction: row; + align-items: center; + gap: 4px; color: var(--color-white); font-size: ${typography.fontSize['2xs']}; font-weight: var(--font-weight-medium); line-height: 20px; + + img { + width: 14px; + height: 14px; + flex-shrink: 0; + } + } + + .titleSkeletonIcon { + width: 14px; + height: 14px; + flex-shrink: 0; + } + + .titleSkeletonText { + display: flex; + align-items: center; + height: 20px; } `; @@ -26,6 +46,7 @@ export const FollowContainer = styled.div` flex-direction: row; justify-content: space-between; align-items: center; + min-height: 58px; img { cursor: pointer; @@ -73,6 +94,37 @@ export const FollowContainer = styled.div` border: 0.5px solid #888; } } + + .skeletonItem { + cursor: default; + } + } + + .arrowSkeleton { + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } +`; + +export const FollowListLoading = styled.div` + display: flex; + align-items: center; + min-height: 58px; + + .placeholderList { + display: flex; + gap: 12px; + } + + .placeholderItem { + width: 36px; + height: 36px; + border-radius: 50%; + background-color: var(--color-darkgrey-dark); } `; diff --git a/src/components/feed/FollowList.tsx b/src/components/feed/FollowList.tsx index 5b7f7e0b..cb3bf945 100644 --- a/src/components/feed/FollowList.tsx +++ b/src/components/feed/FollowList.tsx @@ -4,9 +4,14 @@ import rightArrow from '../../assets/feed/rightArrow.svg'; import people from '../../assets/feed/people.svg'; import character from '../../assets/feed/character.svg'; import { getRecentFollowing, type RecentWriterData } from '@/api/users/getRecentFollowing'; +import Skeleton from '@/shared/ui/Skeleton'; import { Container, FollowContainer, EmptyFollowerContainer } from './FollowList.styled'; -const FollowList = () => { +interface FollowListProps { + onLoadingChange?: (loading: boolean) => void; +} + +const FollowList = ({ onLoadingChange }: FollowListProps) => { const navigate = useNavigate(); const [myFollowings, setMyFollowings] = useState([]); const [loading, setLoading] = useState(true); @@ -14,7 +19,8 @@ const FollowList = () => { const fetchRecentFollowing = async () => { try { setLoading(true); - const response = await getRecentFollowing(); + const minLoadingTime = new Promise(resolve => setTimeout(resolve, 500)); + const [response] = await Promise.all([getRecentFollowing(), minLoadingTime]); if (response.isSuccess) { setMyFollowings(response.data.myFollowingUsers); @@ -33,6 +39,10 @@ const FollowList = () => { fetchRecentFollowing(); }, []); + useEffect(() => { + onLoadingChange?.(loading); + }, [loading, onLoadingChange]); + const hasFollowers = myFollowings.length > 0; const visible = hasFollowers ? myFollowings.slice(0, 10) : []; @@ -50,12 +60,37 @@ const FollowList = () => { return ( -
- -
내 띱
-
{loading ? ( - <> +
+
+ +
+
+ +
+
+ ) : ( +
+ 내 띱 +
내 띱
+
+ )} + {loading ? ( + +
+ {Array.from({ length: 6 }).map((_, i) => ( +
+ +
+ +
+
+ ))} +
+
+ +
+
) : hasFollowers ? (
diff --git a/src/components/feed/MyFeed.styled.ts b/src/components/feed/MyFeed.styled.ts index 3466d5d2..12871aef 100644 --- a/src/components/feed/MyFeed.styled.ts +++ b/src/components/feed/MyFeed.styled.ts @@ -3,7 +3,6 @@ import { colors, typography } from '@/styles/global/global'; export const Container = styled.div` min-height: 100vh; - padding-top: 136px; padding-bottom: 125px; //이전 76px background-color: var(--color-black-main); `; diff --git a/src/components/feed/TotalFeed.styled.ts b/src/components/feed/TotalFeed.styled.ts index b119d34a..39c17344 100644 --- a/src/components/feed/TotalFeed.styled.ts +++ b/src/components/feed/TotalFeed.styled.ts @@ -3,7 +3,7 @@ import { colors, typography } from '@/styles/global/global'; export const Container = styled.div` min-height: 100vh; - padding-top: 136px; + /* padding-top: 136px; */ padding-bottom: 125px; //이전 76px background-color: var(--color-black-main); `; diff --git a/src/components/feed/TotalFeed.tsx b/src/components/feed/TotalFeed.tsx index 65b6f17a..0e7f64e8 100644 --- a/src/components/feed/TotalFeed.tsx +++ b/src/components/feed/TotalFeed.tsx @@ -1,4 +1,3 @@ -import FollowList from './FollowList'; import FeedPost from './FeedPost'; import type { FeedListProps } from '../../types/post'; import { Container, EmptyState } from './TotalFeed.styled'; @@ -8,7 +7,6 @@ const TotalFeed = ({ showHeader, posts = [], isTotalFeed, isLast = false }: Feed return ( - {hasPosts ? ( posts.map((post, index) => ( { const location = useLocation(); const initialTabFromState = (location.state as { initialTab?: string } | null)?.initialTab; const [activeTab, setActiveTab] = useState(initialTabFromState ?? tabs[0]); + const [isFollowListLoading, setIsFollowListLoading] = useState(activeTab === '피드'); const { waitForToken } = useSocialLoginToken(); @@ -77,8 +79,17 @@ const Feed = () => { window.scrollTo(0, 0); }, [activeTab]); + useEffect(() => { + if (activeTab === '피드') { + setIsFollowListLoading(true); + } + }, [activeTab]); + const currentFeed = activeTab === '피드' ? totalFeed : myFeed; - const showInitialLoading = currentFeed.isLoading && currentFeed.items.length === 0; + const showFeedInitialLoading = totalFeed.isLoading && totalFeed.items.length === 0; + const showMyFeedInitialLoading = myFeed.isLoading && myFeed.items.length === 0; + const showInitialLoading = + activeTab === '피드' ? showFeedInitialLoading || isFollowListLoading : showMyFeedInitialLoading; return ( @@ -88,6 +99,7 @@ const Feed = () => { rightButtonClick={handleNoticeButton} /> + {activeTab === '피드' && } {showInitialLoading ? ( activeTab === '내 피드' ? ( diff --git a/src/shared/ui/Skeleton/feed/OtherFeedSkeleton.styled.ts b/src/shared/ui/Skeleton/feed/OtherFeedSkeleton.styled.ts index ee76843e..8c950271 100644 --- a/src/shared/ui/Skeleton/feed/OtherFeedSkeleton.styled.ts +++ b/src/shared/ui/Skeleton/feed/OtherFeedSkeleton.styled.ts @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; export const SkeletonContainer = styled.div<{ paddingTop?: number }>` - padding-top: ${({ paddingTop }) => (paddingTop !== undefined ? `${paddingTop}px` : '56px')}; + /* padding-top: ${({ paddingTop }) => (paddingTop !== undefined ? `${paddingTop}px` : '56px')}; */ background-color: var(--color-black-main); min-height: 100vh; `;