Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 마이리스트, 콜라보리스트 페이지 전체 리스트 조회 무한스크롤 구현 #24

Merged
16 changes: 11 additions & 5 deletions src/app/_api/list/getAllList.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import { AllListType } from '@/lib/types/listType';

export async function getAllList(userId: number, type: string, category?: string) {
const query = `${category ? `${category}` : 'entire'}`;
export async function getAllList(userId: number, type: string, category: string, cursorId?: number) {
const params = new URLSearchParams({
type,
category,
size: '5',
});

const response = await axiosInstance.get<AllListType>(
`/users/${userId}/lists?type=${type}&category=${query}&size=10`
);
if (cursorId) {
params.append('cursorId', cursorId.toString());
}

const response = await axiosInstance.get<AllListType>(`/users/${userId}/lists?${params.toString()}`);

return response.data;
}
14 changes: 11 additions & 3 deletions src/app/user/[userId]/_components/Card.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { style, createVar } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';

export const listColor = createVar();

Expand All @@ -9,14 +10,15 @@ export const container = style({

borderRadius: '1.5rem',
backgroundColor: listColor,
border: `1px solid ${vars.color.gray5}`,
});

export const title = style({
padding: '1.2rem 0 2rem 0',

fontSize: '1.7rem',
fontWeight: '600',
color: 'var(--text-text-grey-dark, #202020)',
color: vars.color.black,
textAlign: 'right',
letterSpacing: '-0.51px',
wordBreak: 'keep-all',
Expand All @@ -28,7 +30,7 @@ export const list = style({

fontSize: '1.2rem',
fontWeight: '400',
color: 'var(--text-text-grey-dark, #202020)',
color: vars.color.black,
lineHeight: '2.5rem',
letterSpacing: '-0.36px',
});
Expand All @@ -46,7 +48,7 @@ export const lockText = style({
fontSize: '1.1rem',
fontWeight: '400',
letterSpacing: '-0.33px',
color: '#AFB1B6',
color: vars.color.gray7,
});

export const item = style({
Expand All @@ -58,3 +60,9 @@ export const item = style({
export const rank = style({
width: '1.2rem',
});

export const itemTitle = style({
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
});
2 changes: 1 addition & 1 deletion src/app/user/[userId]/_components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function Card({ list, isOwner }: CardProps) {
{item.ranking}
{'.'}
</span>
<span>{item.title}</span>
<span className={styles.itemTitle}>{item.title}</span>
</li>
))}
</ul>
Expand Down
14 changes: 8 additions & 6 deletions src/app/user/[userId]/_components/Categories.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { style } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';

export const container = style({
padding: '2.1rem 0 1.5rem 1.5rem',
Expand All @@ -17,19 +18,20 @@ export const container = style({
export const button = style({
padding: '0.8rem 1.2rem',

backgroundColor: '#FFF',
backgroundColor: vars.color.white,
borderRadius: '5rem',
border: '1px solid #DEDEDE',
border: `1px solid ${vars.color.gray5}`,

/** TODO - 공용폰트 body large 적용 */
fontSize: '1.6rem',
fontWeight: '500',
color: '#828282',
fontWeight: '400',
color: vars.color.gray9,
letterSpacing: '-0.48px',
whiteSpace: 'nowrap',
});

export const variant = style({
backgroundColor: '#0047FF',
color: '#FFF',
backgroundColor: vars.color.blue,
color: vars.color.white,
border: 'none',
});
11 changes: 3 additions & 8 deletions src/app/user/[userId]/_components/Categories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
- [ ] 클릭했을때 로직 (상위요소에 핸들러 고민) (리팩토링)
*/

import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';

import * as styles from './Categories.css';
Expand All @@ -16,21 +15,17 @@ import { QUERY_KEYS } from '@/lib/constants/queryKeys';

interface CategoriesProps {
handleFetchListsOnCategory: (category: string) => void;
selectedCategory: string;
}

export const DEFAULT_CATEGORY = 'entire';

export default function Categories({ handleFetchListsOnCategory }: CategoriesProps) {
const [selected, setSelected] = useState(DEFAULT_CATEGORY);

export default function Categories({ handleFetchListsOnCategory, selectedCategory }: CategoriesProps) {
const { data } = useQuery<CategoryType[]>({
queryKey: [QUERY_KEYS.getCategories],
queryFn: getCategories,
});

const handleChangeCategory = (category: string) => () => {
handleFetchListsOnCategory(category);
setSelected(category);
};

return (
Expand All @@ -39,7 +34,7 @@ export default function Categories({ handleFetchListsOnCategory }: CategoriesPro
<button
key={category.codeValue}
onClick={handleChangeCategory(category.nameValue)}
className={`${styles.button} ${category.nameValue === selected ? styles.variant : ''}`}
className={`${styles.button} ${category.nameValue === selectedCategory ? styles.variant : ''}`}
>
{category.korNameValue}
</button>
Expand Down
10 changes: 8 additions & 2 deletions src/app/user/[userId]/_components/Content.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { style, styleVariants } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';

export const container = style({
width: '100%',
Expand All @@ -7,7 +8,7 @@ export const container = style({
position: 'absolute',
top: 0,

backgroundColor: '#FFF',
backgroundColor: vars.color.white,
borderTopLeftRadius: '2.5rem',
borderTopRightRadius: '2.5rem',
});
Expand All @@ -27,10 +28,11 @@ export const button = style({
width: '100%',
height: '100%',

backgroundColor: 'white',
backgroundColor: vars.color.white,
borderTop: '1px solid rgba(0, 0, 0, 0.25)',
borderBottom: '1px solid rgba(0, 0, 0, 0.10)',

/** TODO - 공용폰트 body large 적용 */
fontSize: '1.6rem',
fontWeight: '500',
});
Expand Down Expand Up @@ -69,3 +71,7 @@ export const variantLine = styleVariants({
},
],
});

export const target = style({
height: '1px',
});
73 changes: 49 additions & 24 deletions src/app/user/[userId]/_components/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

/**
TODO
- [ ] 무한스크롤 적용
- [ ] 피드페이지 스켈레톤 ui 적용
*/

import Link from 'next/link';
import { useCallback, useEffect, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useEffect, useMemo, useState } from 'react';
import { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query';
import { MasonryGrid } from '@egjs/react-grid';

import * as styles from './Content.css';
Expand All @@ -23,42 +22,67 @@ import { getAllList } from '@/app/_api/list/getAllList';

import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import { UserType } from '@/lib/types/userProfileType';
import { ListType } from '@/lib/types/listType';
import { AllListType } from '@/lib/types/listType';

import useIntersectionObserver from '@/hooks/useIntersectionObserver';

interface ContentProps {
userId: number;
type: string;
}

const DEFAULT_CATEGORY = 'entire';

export default function Content({ userId, type }: ContentProps) {
const [listGrid, setListGrid] = useState<ListType[]>([]);
const queryClient = useQueryClient();
const [selectedCategory, setSelectedCategory] = useState(DEFAULT_CATEGORY);

const { data: userData } = useQuery<UserType>({
queryKey: [QUERY_KEYS.userOne, userId],
queryFn: () => getUserOne(userId),
});

/** 무한스크롤시 리액트 쿼리로 불러오는게 더 나을지에 대한 고민 때문에 주석처리 해 놓은 코드 */
// const { data: listData, refetch } = useQuery<AllListType>({
// queryKey: [QUERY_KEYS.getAllList],
// queryFn: () => getAllList(userId, type),
// });

const handleFetchLists = useCallback(
async (category?: string) => {
const data = await getAllList(userId, type, category);
setListGrid(data.feedLists);
const {
data: listsData,
hasNextPage,
fetchNextPage,
isFetching,
} = useInfiniteQuery<AllListType>({
queryKey: [QUERY_KEYS.getAllList, userId, type, selectedCategory],
queryFn: ({ pageParam: cursorId }) => {
return getAllList(userId, type, selectedCategory, cursorId as number);
},
[userId, type]
);
initialPageParam: null,
getNextPageParam: (lastPage) => (lastPage.hasNext ? lastPage.cursorId : null),
});

const handleFetchListsOnCategory = async (category: string) => {
handleFetchLists(category);
const lists = useMemo(() => {
return listsData ? listsData.pages.flatMap(({ feedLists }) => feedLists) : [];
}, [listsData]);

const ref = useIntersectionObserver(() => {
if (hasNextPage) {
fetchNextPage();
}
});

const handleFetchListsOnCategory = (category: string) => {
setSelectedCategory(category);

queryClient.resetQueries({
queryKey: [QUERY_KEYS.getAllList, userId, type, selectedCategory],
exact: true,
});
};

useEffect(() => {
handleFetchLists();
}, [handleFetchLists]);
return () => {
queryClient.removeQueries({
queryKey: [QUERY_KEYS.getAllList, userId, type, selectedCategory],
exact: true,
});
};
}, []);

return (
<div className={styles.container}>
Expand All @@ -75,15 +99,16 @@ export default function Content({ userId, type }: ContentProps) {
) : (
<BlueLineLongIcon className={styles.variantLine.right} />
)}

<Categories handleFetchListsOnCategory={handleFetchListsOnCategory} />
<Categories handleFetchListsOnCategory={handleFetchListsOnCategory} selectedCategory={selectedCategory} />
<div className={styles.cards}>
<MasonryGrid gap={16} defaultDirection={'end'} align={'start'}>
{listGrid.map((list: ListType) => (
{lists.map((list) => (
<Card key={list.id} list={list} isOwner={!!userData?.isOwner} />
))}
</MasonryGrid>
</div>
{isFetching && <div>로딩중</div>}
<div className={styles.target} ref={ref}></div>
</div>
);
}
5 changes: 3 additions & 2 deletions src/app/user/[userId]/_components/FollowButton.css.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { style } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';

export const button = style({
padding: '0.8rem 1.2rem',

backgroundColor: 'var(--Blue, #0047FF)',
backgroundColor: vars.color.blue,
borderRadius: '5rem',

fontSize: '1rem',
fontWeight: '600',
color: '#fff',
color: vars.color.white,
});
7 changes: 4 additions & 3 deletions src/app/user/[userId]/_components/Profile.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { style, createVar } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';

export const imageUrl = createVar();

Expand Down Expand Up @@ -48,7 +49,7 @@ export const profileImage = style({
height: '5rem',

borderRadius: '50%',
border: '2px solid #FFF',
border: `2px solid ${vars.color.white}`,
});

export const info = style({
Expand All @@ -66,7 +67,7 @@ export const user = style({
export const nickName = style({
fontSize: '2rem',
fontWeight: ' 700',
color: '#202020',
color: vars.color.black,
letterSpacing: '-0.6px',
});

Expand Down Expand Up @@ -99,7 +100,7 @@ export const description = style({

fontSize: '1.2rem',
fontWeight: '500',
color: '#333',
color: vars.color.black,
lineHeight: '1.6rem',
letterSpacing: '-0.36px',
});
Loading