Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff9d3f5
Squashed commit of the following:
yulrang Nov 11, 2024
bc4056a
[WIP] Feat: GetCrewList API 연결
yulrang Nov 11, 2024
6ac757f
Merge branch 'develop' into Feat/98/CrewAPI
yulrang Nov 11, 2024
0936ad1
✨ Feat: 백엔드 api 연결
yulrang Nov 11, 2024
e64877f
🐛 Fix: 처음 로딩시 카테고리 초기화
yulrang Nov 11, 2024
ab7d7a9
🐛 Fix: 카테고리 동작 개선
yulrang Nov 12, 2024
b4a70ff
🐛 Fix: 지역 필터링 동작 개선
yulrang Nov 12, 2024
22f3307
✨ Feat: 지역 전체 필터 추가
yulrang Nov 12, 2024
60a3b12
Merge branch 'develop' into Feat/98/CrewAPI
yulrang Nov 12, 2024
1026125
🚨 Fix: 타입 개선, 빌드 오류 수정
yulrang Nov 12, 2024
56bea37
🚧 Chore: workflow 수정
yulrang Nov 12, 2024
1d430b1
♻️ Refactor 코드 개선
yulrang Nov 12, 2024
3a7ce8e
🐛 Fix: 코드 개선
yulrang Nov 12, 2024
ecd941d
✨ Feat: 검색 버튼 추가
yulrang Nov 12, 2024
9a3f685
🐛 Fix: 동작 개선
yulrang Nov 12, 2024
89632d1
🚧 Chore: 경로 변경
yulrang Nov 12, 2024
04225e6
Merge branch 'develop' into Feat/98/CrewAPI
yulrang Nov 12, 2024
ae1729a
🐛 Fix: 콘솔에러 추가
yulrang Nov 12, 2024
b4b356c
⚡️ Fix: 검색 엔터방식으로 변경
yulrang Nov 12, 2024
67886c3
🐛 Fix: 동작개선, 에러메시지 보이기
yulrang Nov 12, 2024
3213309
Merge branch 'Feat/98/CrewAPI' of https://github.com/CodeitFESI4-Team…
yulrang Nov 12, 2024
b9b5cb5
💄 Design: 스타일 수정
yulrang Nov 12, 2024
5687085
🐛 Fix: 에러처리 추가
yulrang Nov 13, 2024
c3382b1
🚨 Fix: 빌드 오류 수정
yulrang Nov 13, 2024
be1480d
🐛 Fix: 타입 수정
yulrang Nov 13, 2024
3c567f3
🐛 Fix: 디폴트이미지 삭제, 데브툴 조건부렌더링
yulrang Nov 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ jobs:

- name: Build test
run: npm run build
env:
NEXT_PUBLIC_API_BASE_URL: ${{secrets.NEXT_PUBLIC_API_BASE_URL}}
9 changes: 9 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,14 @@ const nextConfig = {
},
];
},

async rewrites() {
return [
{
source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`,
},
];
},
};
export default nextConfig;
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@storybook/nextjs": "^8.3.5",
"@storybook/react": "^8.3.5",
"@storybook/testing-library": "^0.2.2",
"@tanstack/react-query-devtools": "^5.59.20",
Copy link

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을 사용하고 있습니다. 다음 중 하나의 조치가 필요합니다:

  • @tanstack/react-query를 ^5.59.20으로 업그레이드
  • @tanstack/react-query-devtools를 ^5.59.16으로 다운그레이드
🔗 Analysis chain

React Query DevTools 의존성이 적절히 추가되었습니다.

개발 도구로서 devDependencies에 올바르게 배치되었습니다. 다만 몇 가지 고려사항이 있습니다:

  1. 버전 호환성을 확인해주세요
  2. 재현 가능한 빌드를 위해 정확한 버전을 고정하는 것을 고려해보세요

패키지 버전 호환성을 확인하기 위해 다음 스크립트를 실행하세요:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify version compatibility between react-query and its devtools

# Extract and compare versions
QUERY_VERSION=$(cat package.json | jq -r '.dependencies["@tanstack/react-query"]')
DEVTOOLS_VERSION=$(cat package.json | jq -r '.devDependencies["@tanstack/react-query-devtools"]')

echo "React Query version: $QUERY_VERSION"
echo "DevTools version: $DEVTOOLS_VERSION"

# Check npm for compatibility information
npm view @tanstack/react-query-devtools@$DEVTOOLS_VERSION peerDependencies

Length of output: 679

"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/node": "^20",
"@types/react": "^18",
Expand Down
Binary file added public/assets/images/img-default.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 11 additions & 10 deletions src/_apis/crew/get-crew-list.ts
Original file line number Diff line number Diff line change
@@ -1,24 +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,
): Promise<MainCrewListResponse> {
const { keyword, mainLocation, mainCategory, subCategory, sortType } = condition;
const { page, size, sort = ['string'] } = pageable;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

sort 매개변수의 기본값이 적절하지 않습니다

sort 매개변수의 기본값으로 ['string']을 사용하는 것은 적절하지 않아 보입니다. 실제 정렬 기준을 반영하는 의미 있는 기본값으로 변경하는 것이 좋습니다.

예시:

- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { page, size, sort = ['string'] } = pageable;
const { page, size, sort = ['createdAt,desc'] } = pageable;


export async function getCrewList(page: number, limit: number): Promise<MainCrewListResponse> {
try {
const response = await fetchApi<MainCrewListResponse>(
`/crews?_page=${page + 1}&_limit=${limit}`,
`/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
Copy link

@coderabbitai coderabbitai bot Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

쿼리 파라미터의 URL 인코딩 필요

쿼리 파라미터를 직접 문자열로 결합하면 특수 문자나 예기치 않은 입력으로 인해 오류가 발생할 수 있습니다. URLSearchParams를 사용하여 파라미터를 적절히 인코딩하는 것을 권장합니다.

수정 제안:

+    const params = new URLSearchParams({
+      keyword,
+      mainLocation,
+      mainCategory,
+      subCategory,
+      sortType,
+      page: page.toString(),
+      size: size.toString(),
+      sort: sort.join(','),
+    });
+    const response = await fetchApi<CrewCardInformResponse>(
+      `/crews/search?${params.toString()}`,
       {
         method: 'GET',
         headers: {
           'Content-Type': 'application/json',
         },
         credentials: 'include', // 인증 정보를 요청에 포함
       },
     );

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

params.toString 사용해서 코드 수정하면 좋을 것 같습니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minkyung5x5, 네, params.toString()을 사용하여 코드를 수정하면 좋을 것 같습니다! 수정해 주셔서 감사합니다.


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

{
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('크루 리스트를 불러오는데 실패했습니다.');
}
Expand Down
28 changes: 13 additions & 15 deletions src/_queries/crew-queries.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { MainCrewList } from '@/src/types/crew-card';
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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

queryKey에 undefined 또는 null 값이 포함되지 않도록 처리하세요.

queryKey 배열에 condition 객체의 속성들이 포함되는데, 만약 어떤 속성이 undefined 또는 null인 경우 캐싱 키가 예상대로 작동하지 않을 수 있습니다. 이를 방지하기 위해 기본 값을 지정하거나 falsy한 값을 필터링하는 것이 좋습니다.

예를 들어, 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] }),
getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]) =>
lastPage.hasNext ? allPages.length : undefined,
};
}
4 changes: 2 additions & 2 deletions src/app/(crew)/my-crew/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { useState } from 'react';
import { useGetCrewQuery } from '@/src/_queries/crew-queries';
import { useGetCrewListQuery } from '@/src/_queries/crew-queries';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import CrewCardList from '@/src/components/common/crew-list/crew-card-list';
import Tabs from '@/src/components/common/tab';
Expand All @@ -17,7 +17,7 @@ export default function MyCrewPage() {
// TODO: fetchCrewData 함수를 사용하여 데이터를 불러오기 : 파라미터 수정 필요
// TODO: 리스트와는 다른 데이터를 사용해야해서 우선 주석처리 했습니다.
// const { data, ref, isFetchingNextPage } =
// useInfiniteScroll<MyCrewListResponse>(useGetCrewQuery());
// useInfiniteScroll<MyCrewListResponse>(useGetCrewListQuery());

return (
<div className="py-8 md:py-12.5">
Expand Down
36 changes: 26 additions & 10 deletions src/app/(crew)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,38 @@
import { useState } from 'react';
import Image from 'next/image';
import { Divider } from '@mantine/core';
import { useGetCrewQuery } from '@/src/_queries/crew-queries';
import { useGetCrewListQuery } 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 [mainCategory, setMainCategory] = useState('');
const [subCategory, setSubCategory] = useState('');
const [sort, setSort] = useState<string | null>('latest');
const [region, setRegion] = useState<string | null>('all');
const [region, setRegion] = useState<string>('');
const [search, setSearch] = useState('');

const { data, ref, isFetchingNextPage } =
useInfiniteScroll<MainCrewListResponse>(useGetCrewQuery());
const handleRegionChange = (newValue: string) => {
const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue);
if (selectedRegion?.main.label === '지역 전체') return '';
return selectedRegion ? selectedRegion.main.label : '';
};

const { data, ref, isFetchingNextPage } = useInfiniteScroll(
useGetCrewListQuery({
keyword: search,
mainLocation: handleRegionChange(region),
mainCategory,
subCategory,
sortType: sort === 'latest' ? 'LATEST' : 'POPULAR',
}),
);

return (
<div className="py-8 md:py-12.5">
Expand Down Expand Up @@ -55,10 +67,12 @@ export default function Home() {
name="region"
variant="default"
data={regionData.map((dataItem) => dataItem.main)}
placeholder="전체"
placeholder="지역 전체"
value={region}
className="w-[130px]"
onChange={setRegion}
onChange={(newValue) => {
setRegion(newValue as string);
}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

타입 캐스팅 개선이 필요합니다.

onChange 핸들러에서의 타입 캐스팅을 더 안전하게 처리할 수 있습니다.

다음과 같이 개선해보세요:

-onChange={(newValue) => {
-  setRegion(newValue as string);
-}}
+onChange={(newValue: string | null) => {
+  if (newValue) setRegion(newValue);
+}}

-onChange={(newValue) => {
-  setSort(newValue as string);
-}}
+onChange={(newValue: string | null) => {
+  if (newValue) setSort(newValue);
+}}

Also applies to: 87-89

/>
<DropDown
name="sort"
Expand All @@ -70,7 +84,9 @@ export default function Home() {
placeholder="최신순"
value={sort}
className="w-[130px]"
onChange={setSort}
onChange={(newValue) => {
setSort(newValue as string);
}}
/>
</div>
</div>
Expand Down
30 changes: 11 additions & 19 deletions src/app/_components/category/category-container/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
'use client';

import { useEffect, useState } from 'react';
import { useState } from 'react';
import category from '@/src/data/category.json';
import InternalCategory from '@/src/app/_components/category/internal-category';
import MainCategory from '@/src/app/_components/category/main-category';
Expand All @@ -18,32 +16,26 @@ export default function CategoryContainer({
setMainCategory,
setSubCategory,
}: CategoryContainerProps) {
const [categoryIndex, setCategoryIndex] = useState(0);

useEffect(() => {
if (subCategory !== category[categoryIndex].items[0].value) {
setSubCategory(category[categoryIndex].items[0].value);
}
}, [mainCategory, categoryIndex]);

useEffect(() => {
if (mainCategory !== category[categoryIndex].title.value) {
setMainCategory(category[categoryIndex].title.value);
}
}, [subCategory]);
const [categoryIndex, setCategoryIndex] = useState<number | null>(null);

return (
<div className="flex flex-col gap-2 md:gap-4">
<MainCategory
value={mainCategory}
category={category}
onChange={setMainCategory}
onChange={(newValue) => {
setMainCategory(newValue);
setSubCategory('');
}}
onHover={setCategoryIndex}
/>
<InternalCategory
value={subCategory}
category={category[categoryIndex].items}
onChange={setSubCategory}
category={category[categoryIndex ?? 0].items}
onChange={(newValue) => {
setSubCategory(newValue);
setMainCategory(category[categoryIndex ?? 0].title.label);
}}
/>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/_components/category/internal-category/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export default function InternalCategory({ value, category, onChange }: Internal
<li key={item.label} className="snap-align-start flex">
<Button
type="button"
onClick={() => onChange(item.value)}
className={`${pathname?.includes(item.value ?? value) && 'bg-gray-900 text-white'} h-10 min-w-28 items-center justify-center text-nowrap rounded-xl bg-gray-100 px-5 py-2 text-center text-sm font-bold text-gray-400 transition-colors hover:bg-gray-900 hover:text-white md:h-11 md:text-lg`}
onClick={() => onChange(item.label)}
className={`${pathname?.includes(item.label ?? value) && 'bg-gray-900 text-white'} h-10 min-w-28 items-center justify-center text-nowrap rounded-xl bg-gray-100 px-5 py-2 text-center text-sm font-bold text-gray-400 transition-colors hover:bg-gray-900 hover:text-white md:h-11 md:text-lg`}
>
{item.label}
</Button>
Expand Down
4 changes: 2 additions & 2 deletions src/app/_components/category/main-category/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export default function MainCategory({ value, category, onHover, onChange }: Mai
>
<Button
onMouseEnter={() => handleHover(index)}
onClick={() => onChange(item.title.value)}
className={`${pathname?.includes(item.title.value ?? value) ? 'bg-blue-500' : ''} ${activeIndex === index ? 'text-blue-500' : 'text-gray-600'} flex flex-col items-center text-base font-semibold md:flex-row md:text-lg lg:text-xl lg:font-semibold`}
onClick={() => onChange(item.title.label)}
className={`${pathname?.includes(item.title.label ?? value) ? 'bg-blue-500' : ''} ${activeIndex === index ? 'text-blue-500' : 'text-gray-600'} flex flex-col items-center text-base font-semibold md:flex-row md:text-lg lg:text-xl lg:font-semibold`}
>
<h3 className="flex items-center gap-1 lg:gap-2">
<span className="flex">{item.title.label}</span>
Expand Down
2 changes: 2 additions & 0 deletions src/components/client-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { ReactNode } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental';

export default function ClientProvider({ children }: { children: ReactNode }) {
Expand All @@ -16,6 +17,7 @@ export default function ClientProvider({ children }: { children: ReactNode }) {

return (
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

프로덕션 환경에서 ReactQueryDevtools 조건부 렌더링 필요

ReactQueryDevtools가 프로덕션 환경에서도 포함될 수 있는 상태입니다. 다음과 같이 수정이 필요합니다:

  • src/components/client-provider.tsx에서 process.env.NODE_ENV를 확인하여 개발 환경에서만 ReactQueryDevtools를 렌더링하도록 수정해야 합니다.
{process.env.NODE_ENV === 'development' && <ReactQueryDevtools initialIsOpen={false} />}
🔗 Analysis chain

개발 환경에서만 사용되도록 확인 필요

ReactQueryDevtools가 적절하게 추가되었고 initialIsOpen이 false로 설정된 것이 좋습니다. 다만, 프로덕션 빌드에서는 이 컴포넌트가 제외되어야 합니다.

다음 스크립트로 프로덕션 빌드 설정을 확인하겠습니다:


Let me check the actual implementation to verify if the ReactQueryDevtools is conditionally rendered based on the environment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 프로덕션 빌드 설정에서 DevTools가 제외되는지 확인

# next.config.js 또는 next.config.mjs 파일에서 프로덕션 빌드 설정 확인
fd -e js -e mjs -g "next.config.*" --exec cat {} | grep -A 5 "production"

# package.json의 build 스크립트 확인
cat package.json | jq '.scripts.build'

Length of output: 127


Script:

#!/bin/bash
# Check how ReactQueryDevtools is imported and used
rg -A 3 "ReactQueryDevtools" --type tsx --type jsx

Length of output: 78


Script:

#!/bin/bash
# Check the implementation of client-provider.tsx and how ReactQueryDevtools is used
cat src/components/client-provider.tsx

Length of output: 808

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위에 코드 래빗의 의견처럼 디버깅 도구라 dev환경에서만 실행되도록 조건부 랜더링을 추가해야될거같아요!

<ReactQueryStreamedHydration>{children}</ReactQueryStreamedHydration>
</QueryClientProvider>
);
Expand Down
14 changes: 10 additions & 4 deletions src/components/common/crew-list/crew-card-list.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { useGetCrewQuery } from '@/src/_queries/crew-queries';
import { useGetCrewListQuery } from '@/src/_queries/crew-queries';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import ClientProvider from '@/src/components/client-provider';
import { MainCrewListResponse } from '@/src/types/crew-card';
Expand Down Expand Up @@ -28,9 +28,15 @@ export default meta;
type Story = StoryObj<typeof meta>;

function RenderCrewCardList() {
const { data, ref, isFetchingNextPage } =
useInfiniteScroll<MainCrewListResponse>(useGetCrewQuery());

const { data, ref, isFetchingNextPage } = useInfiniteScroll(
useGetCrewListQuery({
keyword: '',
mainLocation: '',
mainCategory: '',
subCategory: '',
sortType: 'LATEST',
}),
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

스토리북 테스트 케이스 보강이 필요합니다.

현재는 기본 케이스만 테스트하고 있습니다. 다양한 필터 조건에 대한 테스트 케이스를 추가하면 좋을 것 같습니다.

다음과 같은 테스트 케이스들을 추가해보시는 것을 추천드립니다:

export const WithKeywordSearch: Story = {
  render: () => (
    <RenderCrewCardList initialCondition={{ keyword: '개발자', sortType: 'LATEST' }} />
  ),
};

export const WithLocationFilter: Story = {
  render: () => (
    <RenderCrewCardList initialCondition={{ mainLocation: '서울', sortType: 'LATEST' }} />
  ),
};

export const WithCategoryFilter: Story = {
  render: () => (
    <RenderCrewCardList 
      initialCondition={{ 
        mainCategory: '개발', 
        subCategory: '웹개발',
        sortType: 'LATEST' 
      }} 
    />
  ),
};

return <CrewCardList data={data} ref={ref} isFetchingNextPage={isFetchingNextPage} />;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/common/crew-list/crew-card-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function CrewCardList(
const crewDataList =
(inWhere === 'my-crew'
? data?.pages.flatMap((page) => page.data as MyCrewList[])
: data?.pages.flatMap((page) => page.data as MainCrewList[])) ?? [];
: data?.pages.flatMap((page) => page.content as MainCrewList[])) ?? [];
const gridColsStyle = inWhere === 'my-crew' ? '' : 'lg:grid-cols-2';

if (!crewDataList.length)
Expand Down Expand Up @@ -68,7 +68,7 @@ function CrewCardList(
: (inform as MainCrewList).totalGatheringCount
}
crewMembers={inWhere === 'my-crew' ? (inform as MyCrewList).crewMembers : undefined}
isConfirmed={inWhere !== 'my-crew' ? (inform as MainCrewList).isConfirmed : undefined}
isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList).isConfirmed}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

타입 안전성과 가독성 개선이 필요합니다.

현재 구현은 간결하지만, 타입 단언과 부정 조건을 함께 사용하고 있어 코드의 의도를 파악하기 어려울 수 있습니다.

다음과 같이 개선해보세요:

-isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList).isConfirmed}
+isConfirmed={inWhere === 'my-crew' ? false : inform.isConfirmed}

또한, 타입 가드를 사용하여 타입 안전성을 높이는 것을 고려해보세요:

function isMainCrewList(crew: MainCrewList | MyCrewList): crew is MainCrewList {
  return 'isConfirmed' in crew;
}

/>
</li>
))}
Expand Down
Loading