From bd64a762066c0eaa18f8a813412b8faab930f6f0 Mon Sep 17 00:00:00 2001 From: hun Date: Thu, 12 Feb 2026 21:16:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EA=B0=80=EA=B2=A9=EB=8C=80=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useDeviceSearch.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/hooks/useDeviceSearch.ts b/src/hooks/useDeviceSearch.ts index 4f6233c..6def01b 100644 --- a/src/hooks/useDeviceSearch.ts +++ b/src/hooks/useDeviceSearch.ts @@ -24,6 +24,35 @@ export const useDeviceSearch = () => { })); }, [brandsData]); + // 가격대 필터를 minPrice/maxPrice로 변환 + const priceRange = useMemo(() => { + if (selectedPrice.length === 0) return { minPrice: undefined, maxPrice: undefined }; + + const prices = selectedPrice.map(value => { + switch (value) { + case 'under-100': + return { min: 0, max: 1000000 }; + case '100-150': + return { min: 1000000, max: 1500000 }; + case '150-200': + return { min: 1500000, max: 2000000 }; + case 'over-200': + return { min: 2000000, max: Infinity }; + default: + return { min: 0, max: Infinity }; + } + }); + + // 선택된 모든 가격대에서 최소값과 최대값 계산 + const minPrice = Math.min(...prices.map(p => p.min)); + const maxPrice = Math.max(...prices.map(p => p.max)); + + return { + minPrice: minPrice > 0 ? minPrice : undefined, + maxPrice: maxPrice < Infinity ? maxPrice : undefined, + }; + }, [selectedPrice]); + // 기기 검색 API 파라미터 구성 const apiSearchParams = useMemo(() => { const deviceType = getCategoryDeviceType(selectedCategory); @@ -33,8 +62,10 @@ export const useDeviceSearch = () => { sortType: getSortType(sortOption), deviceTypes: deviceType ? [deviceType] : undefined, brandIds: selectedBrand ? [Number(selectedBrand)] : undefined, + minPrice: priceRange.minPrice, + maxPrice: priceRange.maxPrice, }; - }, [searchQuery, selectedCategory, sortOption, selectedBrand]); + }, [searchQuery, selectedCategory, sortOption, selectedBrand, priceRange]); // 기기 검색 API 호출 const { From fb63f2d13a912f1ab926a1aae1c9939ba15eb7f6 Mon Sep 17 00:00:00 2001 From: hun Date: Thu, 12 Feb 2026 21:21:19 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EB=82=AE=EC=9D=80=EA=B0=80=EA=B2=A9?= =?UTF-8?q?,=20=EB=86=92=EC=9D=80=EA=B0=80=EA=B2=A9=EC=88=9C=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useDeviceSearch.ts | 89 +++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/src/hooks/useDeviceSearch.ts b/src/hooks/useDeviceSearch.ts index 6def01b..675d65e 100644 --- a/src/hooks/useDeviceSearch.ts +++ b/src/hooks/useDeviceSearch.ts @@ -24,48 +24,53 @@ export const useDeviceSearch = () => { })); }, [brandsData]); - // 가격대 필터를 minPrice/maxPrice로 변환 - const priceRange = useMemo(() => { - if (selectedPrice.length === 0) return { minPrice: undefined, maxPrice: undefined }; - - const prices = selectedPrice.map(value => { - switch (value) { - case 'under-100': - return { min: 0, max: 1000000 }; - case '100-150': - return { min: 1000000, max: 1500000 }; - case '150-200': - return { min: 1500000, max: 2000000 }; - case 'over-200': - return { min: 2000000, max: Infinity }; - default: - return { min: 0, max: Infinity }; - } - }); - - // 선택된 모든 가격대에서 최소값과 최대값 계산 - const minPrice = Math.min(...prices.map(p => p.min)); - const maxPrice = Math.max(...prices.map(p => p.max)); - - return { - minPrice: minPrice > 0 ? minPrice : undefined, - maxPrice: maxPrice < Infinity ? maxPrice : undefined, - }; - }, [selectedPrice]); - // 기기 검색 API 파라미터 구성 const apiSearchParams = useMemo(() => { const deviceType = getCategoryDeviceType(selectedCategory); + + // 가격대 필터를 minPrice/maxPrice로 변환 + let minPrice: number | undefined = undefined; + let maxPrice: number | undefined = undefined; + + if (selectedPrice.length > 0) { + const prices = selectedPrice.map(value => { + switch (value) { + case 'under-100': + return { min: 0, max: 1000000 }; + case '100-150': + return { min: 1000000, max: 1500000 }; + case '150-200': + return { min: 1500000, max: 2000000 }; + case 'over-200': + return { min: 2000000, max: Infinity }; + default: + return { min: 0, max: Infinity }; + } + }); + + // 선택된 모든 가격대에서 최소값과 최대값 계산 + const calculatedMin = Math.min(...prices.map(p => p.min)); + const calculatedMax = Math.max(...prices.map(p => p.max)); + + minPrice = calculatedMin > 0 ? calculatedMin : undefined; + maxPrice = calculatedMax < Infinity ? calculatedMax : undefined; + } + + // 가격 정렬은 클라이언트에서 처리하므로 API에는 기본 정렬 사용 + const apiSortType = (sortOption === 'price-low' || sortOption === 'price-high') + ? 'LATEST' + : getSortType(sortOption); + return { keyword: searchQuery || undefined, size: 24, - sortType: getSortType(sortOption), + sortType: apiSortType, deviceTypes: deviceType ? [deviceType] : undefined, brandIds: selectedBrand ? [Number(selectedBrand)] : undefined, - minPrice: priceRange.minPrice, - maxPrice: priceRange.maxPrice, + minPrice, + maxPrice, }; - }, [searchQuery, selectedCategory, sortOption, selectedBrand, priceRange]); + }, [searchQuery, selectedCategory, sortOption, selectedBrand, selectedPrice]); // 기기 검색 API 호출 const { @@ -77,11 +82,19 @@ export const useDeviceSearch = () => { isError: isSearchError, } = useSearchDevices(apiSearchParams); - // 전체 기기 목록 (모든 페이지 결합) - const allDevices = useMemo(() => - searchData?.pages.flatMap(page => page.devices) ?? [], - [searchData] - ); + // 전체 기기 목록 (모든 페이지 결합 + 클라이언트 사이드 정렬) + const allDevices = useMemo(() => { + const devices = searchData?.pages.flatMap(page => page.devices) ?? []; + + // 가격 정렬은 클라이언트에서 처리 (백엔드 미지원 시) + if (sortOption === 'price-low') { + return [...devices].sort((a, b) => a.price - b.price); + } else if (sortOption === 'price-high') { + return [...devices].sort((a, b) => b.price - a.price); + } + + return devices; + }, [searchData, sortOption]); // 무한 스크롤 트리거 const { targetRef, isIntersecting } = useIntersectionObserver({ rootMargin: '100px' });