[251104] feat: ShopperHouseData Sorting 필터링 기능 구현
SORTING_TYPE_MAP을 고객 요구사항에 맞게 새로 정의: - Price(highest): 가격 높은순 - Price(lowest): 가격 낮은순 - Top Review Rate: 리뷰 평점 높은순 - Most Reviewed: 인기순 (rankInfo 기준) - Newest Arrivals: 기본 순서 유지 filterOptions 업데이트: - 첫번째: API sortingType (동적, 대부분 'LG Recommended') - 나머지: SORTING_TYPE_MAP 정의대로 5개 옵션 sortItems() 함수 리팩토링: - 문자열 기반 switch → 숫자 인덱스 기반 switch (0~4) - 각 정렬 타입별 로직 명확히 구현 - 가격 정렬 (숫자 파싱), 평점 정렬, 인기순 정렬 완료
This commit is contained in:
@@ -31,13 +31,22 @@ const ITEMS_PER_PAGE = 10;
|
||||
|
||||
// 정렬 타입 매핑
|
||||
const SORTING_TYPE_MAP = {
|
||||
0: 'NEW', // New
|
||||
1: 'POPULAR', // Popular
|
||||
2: 'LOW_PRICE', // Low Price
|
||||
3: 'HIGH_PRICE', // High Price
|
||||
4: 'RATING' // Rating
|
||||
0: 'Price(highest)',
|
||||
1: 'Price(lowest)',
|
||||
2: 'Top Review Rate',
|
||||
3: 'Most Reviewed',
|
||||
4: 'Newest Arrivals'
|
||||
};
|
||||
|
||||
// 📌 [251104] 이전 버전 (더 이상 사용하지 않음 - 참고용으로 유지)
|
||||
// const SORTING_TYPE_MAP_OLD = {
|
||||
// 0: 'NEW', // New
|
||||
// 1: 'POPULAR', // Popular
|
||||
// 2: 'LOW_PRICE', // Low Price
|
||||
// 3: 'HIGH_PRICE', // High Price
|
||||
// 4: 'RATING' // Rating
|
||||
// };
|
||||
|
||||
// sortingType 문자열을 읽기 쉬운 라벨로 변환
|
||||
// 예: "LG_RECOMMENDED" → "Lg Recommended"
|
||||
// 예: "BEST_SELLER" → "Best Seller"
|
||||
@@ -57,7 +66,7 @@ export const HOW_ABOUT_THESE_MODES = {
|
||||
RESPONSE: 'response', // 응답 버전 (팝업)
|
||||
};
|
||||
|
||||
// 프론트엔드 정렬 함수들
|
||||
// 프론트엔드 정렬 함수들 (SORTING_TYPE_MAP 기반)
|
||||
const sortItems = (items, sortType) => {
|
||||
if (!items || items.length === 0) return items;
|
||||
|
||||
@@ -78,12 +87,53 @@ const sortItems = (items, sortType) => {
|
||||
console.log('[SearchResultsNew] ✅ API 정렬 (기본 순서 유지)');
|
||||
return sortedItems;
|
||||
|
||||
case 'NEW': // 신상품 (기본 정렬)
|
||||
console.log('[SearchResultsNew] ✅ NEW 정렬 (기본 순서 유지)');
|
||||
return sortedItems;
|
||||
case 0: { // Price(highest) - 가격 높은순
|
||||
console.log('[SearchResultsNew] ✅ Price(highest) 정렬 (가격 높은순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const priceA = parseInt(a.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
const priceB = parseInt(b.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
return priceB - priceA;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 데이터 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
dcPrice: item.dcPrice,
|
||||
parsedPrice: parseInt(item.dcPrice?.replace(/[^0-9]/g, '') || '0')
|
||||
})));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'POPULAR': { // 인기순 (랭킹 정보 기준)
|
||||
console.log('[SearchResultsNew] ✅ POPULAR 정렬 (랭킹순)');
|
||||
case 1: { // Price(lowest) - 가격 낮은순
|
||||
console.log('[SearchResultsNew] ✅ Price(lowest) 정렬 (가격 낮은순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const priceA = parseInt(a.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
const priceB = parseInt(b.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
return priceA - priceB;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 데이터 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
dcPrice: item.dcPrice,
|
||||
parsedPrice: parseInt(item.dcPrice?.replace(/[^0-9]/g, '') || '0')
|
||||
})));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 2: { // Top Review Rate - 리뷰 평점 높은순
|
||||
console.log('[SearchResultsNew] ✅ Top Review Rate 정렬 (리뷰 평점 높은순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const ratingA = parseFloat(a.reviewGrade || '0');
|
||||
const ratingB = parseFloat(b.reviewGrade || '0');
|
||||
console.log(` 평점 비교: ${a.title?.substring(0, 20)}... (${ratingA}) vs ${b.title?.substring(0, 20)}... (${ratingB})`);
|
||||
return ratingB - ratingA;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 데이터 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
reviewGrade: item.reviewGrade
|
||||
})));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 3: { // Most Reviewed - 가장 많이 리뷰된순 (인기순)
|
||||
console.log('[SearchResultsNew] ✅ Most Reviewed 정렬 (인기순)');
|
||||
const result = sortedItems.sort((a, b) => (b.rankInfo || 0) - (a.rankInfo || 0));
|
||||
console.log('[SearchResultsNew] 정렬 후 데이터 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
@@ -92,49 +142,9 @@ const sortItems = (items, sortType) => {
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'LOW_PRICE': { // 낮은 가격순
|
||||
console.log('[SearchResultsNew] ✅ LOW_PRICE 정렬 (낮은 가격순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const priceA = parseInt(a.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
const priceB = parseInt(b.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
console.log(` 가격 비교: ${a.title?.substring(0, 20)}... (${priceA}) vs ${b.title?.substring(0, 20)}... (${priceB})`);
|
||||
return priceA - priceB;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 가격순 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
dcPrice: item.dcPrice,
|
||||
parsedPrice: parseInt(item.dcPrice?.replace(/[^0-9]/g, '') || '0')
|
||||
})));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'HIGH_PRICE': { // 높은 가격순
|
||||
console.log('[SearchResultsNew] ✅ HIGH_PRICE 정렬 (높은 가격순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const priceA = parseInt(a.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
const priceB = parseInt(b.dcPrice?.replace(/[^0-9]/g, '') || '0');
|
||||
return priceB - priceA;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 높은 가격순 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
dcPrice: item.dcPrice
|
||||
})));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'RATING': { // 평점순
|
||||
console.log('[SearchResultsNew] ✅ RATING 정렬 (평점순)');
|
||||
const result = sortedItems.sort((a, b) => {
|
||||
const ratingA = parseFloat(a.reviewGrade || '0');
|
||||
const ratingB = parseFloat(b.reviewGrade || '0');
|
||||
console.log(` 평점 비교: ${a.title?.substring(0, 20)}... (${ratingA}) vs ${b.title?.substring(0, 20)}... (${ratingB})`);
|
||||
return ratingB - ratingA;
|
||||
});
|
||||
console.log('[SearchResultsNew] 정렬 후 평점순 샘플:', result.slice(0, 3).map(item => ({
|
||||
title: item.title?.substring(0, 30) + '...',
|
||||
reviewGrade: item.reviewGrade
|
||||
})));
|
||||
return result;
|
||||
case 4: { // Newest Arrivals - 최신순 (기본 순서 유지)
|
||||
console.log('[SearchResultsNew] ✅ Newest Arrivals 정렬 (기본 순서 유지)');
|
||||
return sortedItems;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -272,18 +282,18 @@ const SearchResultsNew = ({
|
||||
].filter(Boolean);
|
||||
};
|
||||
|
||||
// 동적 정렬 옵션 배열 (인덱스 기반)
|
||||
// 동적 정렬 옵션 배열 - SORTING_TYPE_MAP 기반
|
||||
const filterOptions = useMemo(() => {
|
||||
const apiSortingType = convertedShopperHouseItems?.[0]?.sortingType;
|
||||
const apiLabel = formatSortingTypeLabel(apiSortingType);
|
||||
|
||||
return [
|
||||
{ label: apiLabel, value: 'api' }, // ⭐ 첫번째: API sortingType (동적)
|
||||
{ label: 'New', value: 'NEW' }, // 두번째: 신상품
|
||||
{ label: 'Popular', value: 'POPULAR' }, // 세번째: 인기순
|
||||
{ label: 'Low Price', value: 'LOW_PRICE' }, // 네번째: 낮은 가격순
|
||||
{ label: 'High Price', value: 'HIGH_PRICE' }, // 다섯번째: 높은 가격순
|
||||
{ label: 'Rating', value: 'RATING' } // 여섯번째: 평점순
|
||||
{ label: apiLabel, value: 'api' }, // ⭐ 첫번째: API sortingType (동적, 주로 'LG Recommended')
|
||||
{ label: SORTING_TYPE_MAP[0], value: 0 }, // 두번째: Price(highest)
|
||||
{ label: SORTING_TYPE_MAP[1], value: 1 }, // 세번째: Price(lowest)
|
||||
{ label: SORTING_TYPE_MAP[2], value: 2 }, // 네번째: Top Review Rate
|
||||
{ label: SORTING_TYPE_MAP[3], value: 3 }, // 다섯번째: Most Reviewed
|
||||
{ label: SORTING_TYPE_MAP[4], value: 4 } // 여섯번째: Newest Arrivals
|
||||
];
|
||||
}, [convertedShopperHouseItems]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user