Skip to content

Commit 9951bc6

Browse files
authored
Merge pull request #583 from depromeet/develop
배포용 PR
2 parents 86bc18b + 7e56874 commit 9951bc6

File tree

7 files changed

+114
-6
lines changed

7 files changed

+114
-6
lines changed

src/apis/feed.ts

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ type GetFeedMeResponse = Array<FeedItemType>;
77

88
type GetFeedByMemberIdResponse = Array<FeedBaseType>;
99

10+
export type FeedVisibilityType = 'ALL' | 'FOLLOWER' | 'NONE';
11+
1012
export const FEED_API = {
1113
getFeedMe: async (): Promise<GetFeedMeResponse> => {
1214
const { data } = await apiInstance.get('/feed/me');
@@ -16,6 +18,10 @@ export const FEED_API = {
1618
const { data } = await apiInstance.get(`/feed/${memberId}`);
1719
return data;
1820
},
21+
getFeedList: async (visibility: FeedVisibilityType): Promise<GetFeedMeResponse> => {
22+
const { data } = await apiInstance.get('/feed', { params: { visibility } });
23+
return data;
24+
},
1925
};
2026

2127
export const useFeedMe = (options?: UseQueryOptions<GetFeedMeResponse>) => {
@@ -33,3 +39,11 @@ export const useFeedByMemberId = (memberId: number, options?: UseQueryOptions<Ge
3339
queryFn: () => FEED_API.getFeed(memberId),
3440
});
3541
};
42+
43+
export const useGetFeedList = (visibility: FeedVisibilityType, options?: UseQueryOptions<GetFeedMeResponse>) => {
44+
return useQuery<GetFeedMeResponse>({
45+
...options,
46+
queryKey: getQueryKey('feedList', { visibility }),
47+
queryFn: () => FEED_API.getFeedList(visibility),
48+
});
49+
};

src/apis/getQueryKey.ts

+5
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,15 @@ type QueryList = {
3636
missionId: string;
3737
};
3838
finishedMissions: undefined;
39+
40+
// feed
3941
feedMe: undefined;
4042
feed: {
4143
memberId: number;
4244
};
45+
feedList: {
46+
visibility: string;
47+
};
4348

4449
// reaction
4550
reactions: {

src/app/feed/FeedItem.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function FeedItem({
5454
<p className={missionNameCss}>{name}</p>
5555
{remark && <p className={remarkCss}>{remark}</p>}
5656
<p className={captionCss}>
57-
{sinceDay}일차 <div className={dotCss} /> {dayjs(startedAt).format('YYYY년 MM월 DD일')}
57+
{sinceDay}일차 <span className={dotCss} /> {dayjs(startedAt).format('YYYY년 MM월 DD일')}
5858
</p>
5959
</div>
6060
</Link>
@@ -150,6 +150,7 @@ const captionCss = css({
150150
});
151151

152152
const dotCss = css({
153+
display: 'block',
153154
width: '2px',
154155
height: '2px',
155156
borderRadius: '50%',

src/app/feed/FeedList.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
'use client';
2-
import { useFeedMe } from '@/apis/feed';
2+
3+
import { type FeedItemType } from '@/apis/schema/feed';
34
import FeedItem, { FeedSkeletonItem } from '@/app/feed/FeedItem';
45
import Empty from '@/components/Empty/Empty';
56
import { ROUTER } from '@/constants/router';
67
import { css } from '@styled-system/css';
78

8-
function FeedList() {
9-
const { data } = useFeedMe();
9+
function FeedList({ data }: { data?: Array<FeedItemType> }) {
1010
if (!data)
1111
return (
1212
<ul className={feedListCss}>

src/app/feed/FeedSection.tsx

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use client';
2+
3+
import { useEffect } from 'react';
4+
import { type FeedVisibilityType, useGetFeedList } from '@/apis/feed';
5+
import FeedList from '@/app/feed/FeedList';
6+
import Tab from '@/components/Tab/Tab';
7+
import { useTab } from '@/components/Tab/Tab.hooks';
8+
import useShowGuide, { GUIDE_KEY } from '@/hooks/useShowGuide';
9+
import { css } from '@/styled-system/css';
10+
11+
const FEED_TABS: { id: FeedVisibilityType; tabName: string }[] = [
12+
{
13+
id: 'ALL',
14+
tabName: '전체',
15+
},
16+
{
17+
id: 'FOLLOWER',
18+
tabName: '팔로워',
19+
},
20+
];
21+
22+
function FeedSection() {
23+
const tabProps = useTab(FEED_TABS, 'FOLLOWER');
24+
25+
const { data, isLoading } = useGetFeedList(tabProps.activeTab as FeedVisibilityType);
26+
const feeds = data?.filter((feed) => feed.recordImageUrl); // 이미지 없는 경우가 있음. 나중에 리팩토링 + 서버와 이야기, FeedItem에 ErrorBoundary 적용해도 좋을 듯.
27+
28+
// NOTE: 초기에 팔로워의 피드가 없는 상태라면, 전체 피드로 변경
29+
useEffect(() => {
30+
if (!isLoading) {
31+
if (feeds?.length === 0) {
32+
tabProps.onTabClick(FEED_TABS[0]);
33+
}
34+
}
35+
}, [isLoading]);
36+
37+
useShowGuide(GUIDE_KEY.ALL_FEED_OPEN, 'appBar');
38+
39+
return (
40+
<div>
41+
<div className={tabWrapperCss}>
42+
<Tab {...tabProps} />
43+
</div>
44+
<FeedList data={feeds} />
45+
</div>
46+
);
47+
}
48+
49+
export default FeedSection;
50+
51+
const tabWrapperCss = css({
52+
padding: '16px 16px 4px 16px',
53+
});

src/app/feed/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import FeedList from '@/app/feed/FeedList';
1+
import FeedSection from '@/app/feed/FeedSection';
22
import AppBar from '@/app/home/AppBar';
33
import AppBarBottom from '@/components/AppBarBottom/AppBarBottom';
44
import BottomDim from '@/components/BottomDim/BottomDim';
@@ -7,7 +7,7 @@ export default function FeedPage() {
77
return (
88
<>
99
<AppBar />
10-
<FeedList />
10+
<FeedSection />
1111
<BottomDim type={'bottomDim2'} />
1212
<AppBarBottom />
1313
</>

src/hooks/useShowGuide.ts

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client';
2+
3+
import { useEffect } from 'react';
4+
import { type SnackBarOffset } from '@/components/SnackBar/SnackBar.types';
5+
import { useSnackBar } from '@/components/SnackBar/SnackBarProvider';
6+
7+
export enum GUIDE_KEY {
8+
ALL_FEED_OPEN = 'ALL_FEED_OPEN',
9+
}
10+
11+
const GuideMessage: Record<GUIDE_KEY, string> = {
12+
[GUIDE_KEY.ALL_FEED_OPEN]: '상단에 전체 피드 기능이 추가되었습니다. 확인해보세요!',
13+
};
14+
15+
function useShowGuide(key: GUIDE_KEY, offset?: SnackBarOffset) {
16+
const { triggerSnackBar } = useSnackBar();
17+
18+
const showGuide = () => {
19+
triggerSnackBar({
20+
message: GuideMessage[key],
21+
offset,
22+
});
23+
};
24+
25+
useEffect(() => {
26+
if (typeof window === 'undefined') return;
27+
if (!key) return;
28+
if (localStorage.getItem(key)) return;
29+
30+
showGuide();
31+
localStorage.setItem(key, 'true');
32+
}, []);
33+
}
34+
35+
export default useShowGuide;

0 commit comments

Comments
 (0)