Skip to content

Commit 173d0d1

Browse files
authored
Merge pull request #43 from codeit-sprint-part4-8-1/feat-F81-10-메인페이지
Feat: 체험 정렬 순서 드롭다운 기능 구현
2 parents 1c800a8 + ffa71f9 commit 173d0d1

File tree

7 files changed

+55
-15
lines changed

7 files changed

+55
-15
lines changed

src/components/@Shared/category/MainCategory.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default function MainCategory({
99
}: MainCategoryProps) {
1010
const CATEGORY_LIST = [
1111
'전체',
12-
'문화예술',
12+
'문화예술',
1313
'식음료',
1414
'스포츠',
1515
'투어',

src/components/@Shared/dropDown/DropDownMenu.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { motion } from 'framer-motion';
2-
import { useState } from 'react';
2+
import { useEffect, useState } from 'react';
33
import clsx from 'clsx';
44

55
interface FilterList {
@@ -11,6 +11,8 @@ interface DropDownMenuProps {
1111
size?: string;
1212
filterList: FilterList[];
1313
setFilterStatus: React.Dispatch<React.SetStateAction<string | null>>;
14+
setSelectedSort: (sort: string | null) => void;
15+
defaultText?: string;
1416
}
1517

1618
/**
@@ -31,9 +33,18 @@ interface DropDownMenuProps {
3133
export default function DropDownMenu({
3234
filterList,
3335
setFilterStatus,
36+
setSelectedSort,
37+
defaultText = '전체', // 기본 텍스트 '전체'
3438
}: DropDownMenuProps) {
3539
const [isActive, setIsActive] = useState<boolean>(false);
36-
const [filterText, setFilterText] = useState<string>('전체');
40+
const [filterText, setFilterText] = useState<string>(defaultText); // 기본 텍스트 설정
41+
42+
// filterList의 첫 번째 항목이 있을 경우 filterText를 해당 항목으로 업데이트
43+
useEffect(() => {
44+
if (filterList.length > 0 && filterText === defaultText) {
45+
setFilterText(defaultText); // defaultText가 기본값이면 그대로 두기
46+
}
47+
}, [filterList, defaultText, filterText]);
3748

3849
return (
3950
<div className="relative bg-white z-10">
@@ -73,7 +84,8 @@ export default function DropDownMenu({
7384
onClick={() => {
7485
setFilterText(filter.text);
7586
setIsActive(false);
76-
setFilterStatus(filter.id);
87+
setFilterStatus(filter.id); // 필터 상태 업데이트
88+
setSelectedSort(filter.id); // 정렬 상태 업데이트
7789
}}
7890
>
7991
{filter.text}

src/components/@Shared/dropdown/Dropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from 'react';
22
import { HiChevronDown } from 'react-icons/hi';
33

4-
const categories = ['문화 예술', '식음료', '스포츠', '투어', '관광'];
4+
const categories = ['문화 예술', '식음료', '스포츠', '투어', '관광'];
55

66
interface DropdownProps {
77
selectedCategory: string;

src/components/mainPage/ActivityCard.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from 'react';
22
import Link from 'next/link';
33
import { ActivityCardProps } from '../../types/mainPage/ActivityCardTypes';
44

5+
const defaultImage = '/image/defaultImage.png'; // 기본 이미지
6+
57
export const ActivityCard: React.FC<ActivityCardProps> = ({
68
id,
79
image,
@@ -10,11 +12,18 @@ export const ActivityCard: React.FC<ActivityCardProps> = ({
1012
title,
1113
price,
1214
}) => {
15+
// imageUrl이 없으면 기본 이미지로 대체
16+
const imageUrl = image || defaultImage;
17+
1318
return (
1419
<Link href={`/activity/${id}`} passHref>
1520
<div className="w-full max-w-sm rounded-lg overflow-hidden transform transition-transform hover:scale-105 cursor-pointer">
1621
<div className="w-full h-40 overflow-hidden rounded-lg">
17-
<img src={image} alt={title} className="w-full h-full object-cover" />
22+
<img
23+
src={imageUrl}
24+
alt={title}
25+
className="w-full h-full object-cover"
26+
/>
1827
</div>
1928
<div className="p-3">
2029
<div className="flex items-center text-black text-left">

src/components/mainPage/ActivityList.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ interface Activity {
1313

1414
interface ActivityListProps {
1515
selectedCategory: string | null;
16+
selectedSort: string | null;
1617
}
1718

18-
export default function ActivityList({ selectedCategory }: ActivityListProps) {
19+
export default function ActivityList({
20+
selectedCategory,
21+
selectedSort,
22+
}: ActivityListProps) {
1923
const [activities, setActivities] = useState<Activity[]>([]); // 체험 데이터 상태
2024
const [currentPage, setCurrentPage] = useState(1); // 현재 페이지 상태
2125
const [itemsPerPage, setItemsPerPage] = useState(6); // 한 페이지 당 아이템 수
@@ -74,6 +78,11 @@ export default function ActivityList({ selectedCategory }: ActivityListProps) {
7478
params.category = selectedCategory;
7579
}
7680

81+
// 정렬 옵션을 API에 전달
82+
if (selectedSort) {
83+
params.sort = selectedSort; // 가격 낮은 순 / 가격 높은 순 등의 정렬 값
84+
}
85+
7786
// API 요청
7887
const response = await axios.get(apiUrl, { params });
7988

@@ -86,13 +95,12 @@ export default function ActivityList({ selectedCategory }: ActivityListProps) {
8695
setLoading(false);
8796
} catch (err) {
8897
setError('데이터를 가져오는 데 실패했습니다.');
89-
console.error('API 요청 오류:', err);
9098
setLoading(false);
9199
}
92100
};
93101

94102
fetchActivities(); // 데이터 다시 불러오기
95-
}, [selectedCategory, currentPage, itemsPerPage]);
103+
}, [selectedCategory, selectedSort, currentPage, itemsPerPage]);
96104

97105
// 페이지 변경 시 새 데이터를 가져오는 함수
98106
const handlePageChange = (page: number) => {

src/components/mainPage/Category&DropDown.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@ import MainCategory from '../@Shared/category/MainCategory';
33
import DropDownMenu from '../@Shared/dropDown/DropDownMenu';
44

55
interface CategoryAndDropDownProps {
6-
setSelectedCategory: (category: string | null) => void;
6+
setSelectedCategory: (category: string | null) => void; // 카테고리 상태를 부모 컴포넌트에 전달
7+
setSelectedSort: (sort: string | null) => void; // 정렬 상태를 부모 컴포넌트에 전달
78
}
89

910
export default function CategoryAndDropDown({
1011
setSelectedCategory,
12+
setSelectedSort,
1113
}: CategoryAndDropDownProps) {
1214
const MENU_LIST = [
1315
{
14-
id: null,
16+
id: 'price_asc',
1517
text: '가격 낮은 순',
1618
},
1719
{
18-
id: null,
20+
id: 'price_desc',
1921
text: '가격 높은 순',
2022
},
2123
];
@@ -29,6 +31,8 @@ export default function CategoryAndDropDown({
2931
size={'small'}
3032
filterList={MENU_LIST}
3133
setFilterStatus={setFilterStatus}
34+
setSelectedSort={setSelectedSort}
35+
defaultText={'가격'}
3236
/>
3337
</div>
3438
);

src/pages/index.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import CategoryAndDropDown from '@/components/mainPage/Category&DropDown';
66
import ActivityList from '@/components/mainPage/ActivityList';
77

88
export default function Home() {
9-
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
9+
const [selectedCategory, setSelectedCategory] = useState<string | null>(null); // 선택된 카테고리 상태
10+
const [selectedSort, setSelectedSort] = useState<string | null>(null); // 선택된 정렬 상태
1011

1112
return (
1213
<div className="relative w-full">
@@ -30,11 +31,17 @@ export default function Home() {
3031
</div>
3132
<div className="relative mobile:mt-[40px] tablet2:mt-[60px] pc:mt-[60px] z-30 flex justify-center">
3233
{/* 카테고리 선택 컴포넌트에 선택된 카테고리 상태 전달 */}
33-
<CategoryAndDropDown setSelectedCategory={setSelectedCategory} />
34+
<CategoryAndDropDown
35+
setSelectedCategory={setSelectedCategory}
36+
setSelectedSort={setSelectedSort}
37+
/>
3438
</div>
3539
<div className="relative flex justify-center mobile:mb-[83px] tablet2:mb-[153px] pc:mb-[222px]">
3640
{/* 선택된 카테고리에 맞춰 필터링된 체험 목록을 전달 */}
37-
<ActivityList selectedCategory={selectedCategory} />
41+
<ActivityList
42+
selectedCategory={selectedCategory}
43+
selectedSort={selectedSort}
44+
/>
3845
</div>
3946
</div>
4047
);

0 commit comments

Comments
 (0)