-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/98/crew api 연결 #104
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/98/crew api 연결 #104
Changes from all commits
ff9d3f5
bc4056a
6ac757f
0936ad1
e64877f
ab7d7a9
b4a70ff
22f3307
60a3b12
1026125
56bea37
1d430b1
3a7ce8e
ecd941d
9a3f685
89632d1
04225e6
ae1729a
b4b356c
67886c3
3213309
b9b5cb5
5687085
c3382b1
be1480d
3c567f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,25 +1,25 @@ | ||||||||||||||||
| import { fetchApi } from '@/src/utils/api'; | ||||||||||||||||
| import { MainCrewList, MainCrewListResponse } from '@/src/types/crew-card'; | ||||||||||||||||
| import { ConditionTypes, MainCrewListResponse, PageableTypes } from '@/src/types/crew-card'; | ||||||||||||||||
|
|
||||||||||||||||
| export async function getCrewList(condition: ConditionTypes, pageable: PageableTypes) { | ||||||||||||||||
| const { keyword, mainLocation, mainCategory, subCategory, sortType } = condition; | ||||||||||||||||
| const { page, size, sort = ['string'] } = pageable; | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
예시: - const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;📝 Committable suggestion
Suggested change
|
||||||||||||||||
|
|
||||||||||||||||
| export async function getCrewList(page: number, limit: number): Promise<MainCrewListResponse> { | ||||||||||||||||
| try { | ||||||||||||||||
| const response = await fetchApi<MainCrewListResponse>( | ||||||||||||||||
| `/crews?_page=${page + 1}&_limit=${limit}`, | ||||||||||||||||
| `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`, | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 쿼리 파라미터 처리 개선이 필요합니다
다음과 같이 수정하는 것을 제안합니다: - `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
+ const params = new URLSearchParams({
+ keyword,
+ mainLocation,
+ mainCategory,
+ subCategory,
+ sortType,
+ page: page.toString(),
+ size: size.toString(),
+ sort: sort.join(','),
+ });
+ `/api/crews/search?${params.toString()}`,
|
||||||||||||||||
| { | ||||||||||||||||
| method: 'GET', | ||||||||||||||||
| headers: { | ||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||
| }, | ||||||||||||||||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||||||||||||||||
| }, | ||||||||||||||||
| ); | ||||||||||||||||
| if (!Array.isArray(response)) { | ||||||||||||||||
| throw new Error('서버 응답이 올바른 형식이 아닙니다.'); | ||||||||||||||||
| } | ||||||||||||||||
| const data = response as MainCrewList[]; | ||||||||||||||||
| const hasNext = data.length === limit; | ||||||||||||||||
|
|
||||||||||||||||
| return { data, hasNext }; | ||||||||||||||||
| return response; | ||||||||||||||||
| } catch (error) { | ||||||||||||||||
| throw new Error('크루 리스트를 불러오는데 실패했습니다.'); | ||||||||||||||||
| // eslint-disable-next-line no-console | ||||||||||||||||
| console.error(error); | ||||||||||||||||
| return undefined; | ||||||||||||||||
|
Comment on lines
+21
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 처리 방식 개선 필요 현재 에러 처리 방식에는 다음과 같은 문제가 있습니다:
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return undefined;
+ const errorMessage = error instanceof Error
+ ? error.message
+ : '크루 목록을 가져오는데 실패했습니다';
+ throw new Error(errorMessage);
}📝 Committable suggestion
Suggested change
Comment on lines
+22
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 에러처리를 굳이 여기서 하지 않고 페이지에서 한번에 api 유틸에 있는 ApiError를 사용해서 처리해도 좋을거같습니다! |
||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,26 @@ | ||
| import { MainCrewList } from '@/src/types/crew-card'; | ||
| import { UseInfiniteQueryOptions } from '@tanstack/react-query'; | ||
| import { ConditionTypes, MainCrewListResponse, PageableTypes } from '@/src/types/crew-card'; | ||
| import { getCrewList } from '../_apis/crew/get-crew-list'; | ||
|
|
||
| export function useGetCrewQuery() { | ||
| interface QueryParams { | ||
| pageParam?: number; | ||
| } | ||
|
|
||
| interface Page { | ||
| hasNext: boolean; | ||
| } | ||
|
|
||
| export function useGetCrewListQuery(condition: ConditionTypes) { | ||
| return { | ||
| queryKey: ['crew'], | ||
| queryFn: ({ pageParam = 0 }: QueryParams) => getCrewList(pageParam, 3), | ||
| getNextPageParam: (lastPage: Page, allPages: Page[]) => | ||
| lastPage.hasNext ? allPages.length + 1 : undefined, | ||
| select: (data: MainCrewList[]) => data, // 그대로 반환 | ||
| queryKey: [ | ||
| condition.keyword, | ||
| condition.mainLocation, | ||
| condition.mainCategory, | ||
| condition.subCategory, | ||
| condition.sortType, | ||
| ], | ||
|
Comment on lines
+7
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion queryKey에 undefined 또는 null 값이 포함되지 않도록 처리하세요.
예를 들어, undefined나 null 값을 제거하려면 다음과 같이 수정할 수 있습니다: queryKey: [
condition.keyword,
condition.mainLocation,
condition.mainCategory,
condition.subCategory,
condition.sortType,
].filter(Boolean), |
||
| queryFn: ({ pageParam = 0 }) => | ||
| getCrewList(condition, { page: pageParam, size: 6, sort: [condition.sortType] }).then( | ||
| (response) => { | ||
| if (response === undefined) { | ||
| throw new Error('Response is null'); | ||
| } | ||
| return response; | ||
| }, | ||
| ), | ||
| getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]) => | ||
| lastPage.hasNext ? allPages.length : undefined, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,83 +1,26 @@ | ||
| 'use client'; | ||
| import { getCrewList } from '@/src/_apis/crew/get-crew-list'; | ||
| import FindCrew from '../_components/find-crew/find-crew'; | ||
|
|
||
| import { useState } from 'react'; | ||
| import Image from 'next/image'; | ||
| import { Divider } from '@mantine/core'; | ||
| import { useGetCrewQuery } from '@/src/_queries/crew-queries'; | ||
| import regionData from '@/src/data/region.json'; | ||
| import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; | ||
| import CategoryContainer from '@/src/app/_components/category/category-container'; | ||
| import HeroCrew from '@/src/app/_components/hero/hero-crew'; | ||
| import CrewCardList from '@/src/components/common/crew-list/crew-card-list'; | ||
| import DropDown from '@/src/components/common/input/drop-down'; | ||
| import TextInput from '@/src/components/common/input/text-input'; | ||
| import { MainCrewListResponse } from '@/src/types/crew-card'; | ||
| import IcoSearch from '@/public/assets/icons/ic-search.svg'; | ||
|
|
||
| export default function Home() { | ||
| const [mainCategory, setMainCategory] = useState('cardio_strength'); | ||
| const [subCategory, setSubCategory] = useState('running'); | ||
| const [sort, setSort] = useState<string | null>('latest'); | ||
| const [region, setRegion] = useState<string | null>('all'); | ||
| const [search, setSearch] = useState(''); | ||
| export default async function HomePage() { | ||
| const initialData = await getCrewList( | ||
| { | ||
| keyword: '', | ||
| mainLocation: '', | ||
| mainCategory: '', | ||
| subCategory: '', | ||
| sortType: 'LATEST', | ||
| }, | ||
| { | ||
| page: 0, | ||
| size: 6, | ||
| sort: ['LATEST'], | ||
| }, | ||
| ); | ||
|
Comment on lines
+5
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 'getCrewList' 호출에 대한 에러 처리 구현 권장
코드 수정 예시: export default async function HomePage() {
+ let initialData;
+ try {
initialData = await getCrewList(
{
keyword: '',
mainLocation: '',
mainCategory: '',
subCategory: '',
sortType: 'LATEST',
},
{
page: 0,
size: 6,
sort: ['LATEST'],
},
);
+ } catch (error) {
+ // 에러 처리 로직 추가
+ console.error('Crew 리스트를 가져오는 중 에러 발생:', error);
+ initialData = null;
+ }
const infiniteData = {
pages: [initialData],
pageParams: [],
};
return <FindCrew initialData={infiniteData} />;
}
|
||
|
|
||
| const { data, ref, isFetchingNextPage } = | ||
| useInfiniteScroll<MainCrewListResponse>(useGetCrewQuery()); | ||
| const infiniteData = { | ||
| pages: [initialData], | ||
| pageParams: [], | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="py-8 md:py-12.5"> | ||
| <div className="flex flex-col px-3 md:px-8 lg:px-11.5"> | ||
| <HeroCrew /> | ||
| <CategoryContainer | ||
| mainCategory={mainCategory} | ||
| subCategory={subCategory} | ||
| setMainCategory={setMainCategory} | ||
| setSubCategory={setSubCategory} | ||
| /> | ||
| </div> | ||
| <Divider mx={{ base: 0, md: 32, lg: 34 }} my={24} size={2} color="#E5E7EB" /> | ||
| <div className="px-3 md:px-8 lg:px-11.5"> | ||
| <div className="flex flex-col justify-between gap-2 md:flex-row md:gap-4"> | ||
| <div className="flex-1"> | ||
| <TextInput | ||
| value={search} | ||
| onChange={(e) => setSearch(e.target.value)} | ||
| leftSectionPointerEvents="none" | ||
| leftSection={ | ||
| <Image src={IcoSearch} alt="search" width={21} height={21} className="-mr-4" /> | ||
| } | ||
| placeholder="크루 이름, 위치를 검색하세요." | ||
| inputClassNames="w-full h-11 pl-12 placeholder:text-gray-500 font-pretendard text-base font-medium text-gray-800 rounded-xl" | ||
| /> | ||
| </div> | ||
| <div className="flex-0 flex justify-between gap-2 md:basis-67 md:gap-4"> | ||
| <DropDown | ||
| name="region" | ||
| variant="default" | ||
| data={regionData.map((dataItem) => dataItem.main)} | ||
| placeholder="전체" | ||
| value={region} | ||
| className="w-[130px]" | ||
| onChange={setRegion} | ||
| /> | ||
| <DropDown | ||
| name="sort" | ||
| variant="sort" | ||
| data={[ | ||
| { value: 'latest', label: '최신순' }, | ||
| { value: 'best', label: '인기순' }, | ||
| ]} | ||
| placeholder="최신순" | ||
| value={sort} | ||
| className="w-[130px]" | ||
| onChange={setSort} | ||
| /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <div className="mt-8 px-3 md:px-8 lg:px-11.5"> | ||
| <CrewCardList data={data} ref={ref} isFetchingNextPage={isFetchingNextPage} /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| return <FindCrew initialData={infiniteData} />; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
React Query와 DevTools 버전이 호환되지 않습니다
@tanstack/react-query-devtools@^5.59.20은 @tanstack/react-query@^5.59.20을 peer dependency로 요구하지만, 현재 프로젝트는 ^5.59.16을 사용하고 있습니다. 다음 중 하나의 조치가 필요합니다:
🔗 Analysis chain
React Query DevTools 의존성이 적절히 추가되었습니다.
개발 도구로서 devDependencies에 올바르게 배치되었습니다. 다만 몇 가지 고려사항이 있습니다:
패키지 버전 호환성을 확인하기 위해 다음 스크립트를 실행하세요:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 679